Compilation: clean up dialog including.
[gnumeric.git] / src / print.c
blob4f84f7b2d23555a253c6fc6560eccc58b5cbaf32
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 /*
4 * print.c: Printing routines for Gnumeric
6 * Authors:
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"
19 #include "gnumeric.h"
20 #include "print.h"
22 #include "gui-util.h"
23 #include "gutils.h"
24 #include "sheet-object.h"
25 #include "sheet-object-impl.h"
26 #include "selection.h"
27 #include "workbook.h"
28 #include "workbook-control.h"
29 #include "wbc-gtk.h"
30 #include "command-context.h"
31 #include "dialogs/dialogs.h"
32 #include "gnumeric-conf.h"
33 #include "libgnumeric.h"
34 #include "sheet.h"
35 #include "value.h"
36 #include "cellspan.h"
37 #include "print-info.h"
38 #include "application.h"
39 #include "sheet-style.h"
40 #include "ranges.h"
41 #include "parse-util.h"
42 #include "style-font.h"
43 #include "gnumeric-conf.h"
44 #include <goffice/goffice.h>
46 #include <gtk/gtk.h>
47 #include <gsf/gsf-meta-names.h>
49 #include <glib/gi18n-lib.h>
50 #include <glib/gstdio.h>
51 #include <glib.h>
53 #include <unistd.h>
54 #include <errno.h>
56 #ifdef G_OS_WIN32
57 #include <windows.h>
58 /* see bug #533795. */
59 #define PREVIEW_VIA_PDF
60 #endif
62 /* The following structure is used by the printing system */
64 typedef struct {
65 GList *gnmSheets;
66 Workbook *wb;
67 WorkbookControl *wbc;
68 Sheet *sheet;
69 GtkWidget *button_all_sheets, *button_selected_sheet,
70 *button_spec_sheets;
71 GtkWidget *button_selection, *button_ignore_printarea, *button_print_hidden_sheets;
72 GtkWidget *button_ignore_page_breaks;
73 GtkWidget *spin_from, *spin_to;
74 PrintRange pr;
75 guint to, from;
76 gboolean ignore_pb;
77 guint last_pagination;
78 GnmPrintHFRenderInfo *hfi;
79 GtkWidget *progress;
80 gboolean cancel;
81 gboolean preview;
82 } PrintingInstance;
84 typedef struct {
85 Sheet *sheet;
86 gboolean selection;
87 gboolean ignore_printarea;
88 GArray *column_pagination;
89 GArray *row_pagination;
90 guint pages;
91 } SheetPrintInfo;
93 typedef struct {
94 Sheet *sheet;
95 GnmRange range;
96 gint n_rep_cols;
97 gint n_rep_rows;
98 gint first_rep_cols;
99 gint first_rep_rows;
100 } SheetPageRange;
102 typedef struct {
103 gint rc;
104 gint count;
105 gint first_rep;
106 gint n_rep;
107 } PaginationInfo;
110 GType
111 gnm_print_range_get_type (void)
113 static GType etype = 0;
114 if (etype == 0) {
115 static GEnumValue const values[] = {
116 { GNM_PRINT_SAVED_INFO,
117 "GNM_PRINT_SAVED_INFO",
118 "as-saved"},
119 { GNM_PRINT_ACTIVE_SHEET,
120 "GNM_PRINT_ACTIVE_SHEET",
121 "active-sheet"},
122 { GNM_PRINT_ALL_SHEETS,
123 "GNM_PRINT_ALL_SHEETS",
124 "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",
130 "sheet-range"},
131 { GNM_PRINT_SHEET_SELECTION,
132 "GNM_PRINT_SHEET_SELECTION",
133 "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"},
140 { 0, NULL, NULL }
142 etype = g_enum_register_static ("GnmPrintRange", values);
144 return etype;
148 static PrintingInstance *
149 printing_instance_new (void)
151 PrintingInstance * pi = g_new0 (PrintingInstance,1);
152 pi->hfi = gnm_print_hf_render_info_new ();
153 pi->cancel = FALSE;
154 pi->hfi->pages = -1;
156 return pi;
159 static void
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);
166 g_free (data);
169 static void
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);
174 if (pi->progress) {
175 gtk_widget_destroy (pi->progress);
177 g_free (pi);
180 void
181 gnm_print_sheet_objects (cairo_t *cr,
182 Sheet const *sheet,
183 GnmRange *range,
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);
193 cairo_save (cr);
195 height = sheet_row_get_distance_pts (sheet, range->start.row,
196 range->end.row + 1);
197 width = sheet_col_get_distance_pts (sheet,
198 range->start.col, range->end.col + 1);
200 if (sheet->text_is_rtl)
201 cairo_rectangle (cr,
202 base_x - width, base_y,
203 width, height);
204 else
205 cairo_rectangle (cr,
206 base_x, base_y,
207 width, height);
208 cairo_clip (cr);
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))
218 continue;
220 cairo_save (cr);
221 /* move to top left */
222 if (sheet->text_is_rtl) {
223 double tr_x, tr_y;
224 switch (so->anchor.mode) {
225 case GNM_SO_ANCHOR_ABSOLUTE:
226 tr_x = base_x - 0.5; /* because of leading gridline */
227 tr_y = base_y + 0.5;
228 break;
229 case GNM_SO_ANCHOR_ONE_CELL:
230 tr_x = base_x - 0.5
231 - sheet_col_get_distance_pts (sheet, 0, r->start.col+1)
232 + sheet_col_get_distance_pts (sheet, 0, range->start.col);
233 tr_y = base_y + 0.5
234 + sheet_row_get_distance_pts (sheet, 0, r->start.row)
235 - sheet_row_get_distance_pts (sheet, 0, range->start.row);
236 break;
237 default:
238 tr_x = base_x - 0.5
239 - sheet_col_get_distance_pts (sheet, 0, r->end.col+1)
240 + sheet_col_get_distance_pts (sheet, 0, range->start.col);
241 tr_y = base_y + 0.5
242 + sheet_row_get_distance_pts (sheet, 0, r->start.row)
243 - sheet_row_get_distance_pts (sheet, 0, range->start.row);
244 break;
246 cairo_translate (cr, tr_x, tr_y);
247 } else
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,
252 range->start.col),
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,
257 range->start.row));
259 sheet_object_draw_cairo (so, (gpointer)cr, sheet->text_is_rtl);
260 cairo_restore (cr);
263 g_slist_free (objects);
265 cairo_restore (cr);
268 static void
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,
275 base_x, base_y,
276 (GnmPrintInformation const *) sheet->print_info);
277 gnm_print_sheet_objects (cr, sheet, range, base_x, base_y);
280 static void
281 print_header_gtk (GtkPrintContext *context, cairo_t *cr,
282 double x, double y, double w, double h,
283 char const *name,
284 PangoFontDescription *desc)
286 PangoLayout *layout;
287 gint layout_height;
288 gdouble text_height;
290 cairo_rectangle (cr, x, y, w, h);
291 cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
292 cairo_fill (cr);
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);
312 static void
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;
319 int col;
320 double x;
321 PangoFontDescription *desc;
322 double hscale;
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);
339 if (ci->visible) {
340 if (sheet->text_is_rtl)
341 x -= ci->size_pts * hscale;
343 print_header_gtk (context, cr,
344 x + 0.5, 0,
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);
357 static void
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;
364 int row;
365 double x = 0, y;
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);
383 if (ri->visible) {
384 print_header_gtk (context, cr,
385 x, y + 0.5,
386 row_header_width - 0.5,
387 ri->size_pts - 1,
388 row_name (row), desc);
389 y += ri->size_pts;
393 pango_font_description_free (desc);
396 static PangoLayout *
397 ensure_decoration_layout (GtkPrintContext *context)
399 GnmStyle *style;
400 GnmFont *font;
401 PangoLayout *layout;
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);
410 return layout;
415 * print_hf_element
416 * @pj: printing context
417 * @format:
418 * @side:
419 * @y:
421 * Print a header/footer line.
423 * Position at y, and clip to rectangle.
425 static void
426 print_hf_element (GtkPrintContext *context, cairo_t *cr,
427 G_GNUC_UNUSED Sheet const *sheet,
428 char const *format,
429 PangoAlignment side, gdouble width, gboolean align_bottom,
430 GnmPrintHFRenderInfo *hfi)
432 PangoLayout *layout;
434 gdouble text_height = 0.;
435 char *text;
437 if (format == NULL)
438 return;
440 text = gnm_print_hf_format_render (format, hfi, HF_RENDER_PRINT);
442 if (text == NULL)
443 return;
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);
451 if (align_bottom) {
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);
461 g_free(text);
465 * print_hf_line
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.
473 static void
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);
485 * print_page:
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
492 * regular flow.
494 static gboolean
495 print_page (G_GNUC_UNUSED GtkPrintOperation *operation,
496 GtkPrintContext *context,
497 PrintingInstance * pi,
498 SheetPageRange *gsr)
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;
506 cairo_t *cr;
507 gdouble px, py;
508 gdouble width;
509 gdouble height;
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.;
520 if (px <= 0.)
521 px = 1.;
522 if (py <= 0.)
523 py = 1.;
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) {
562 cairo_save (cr);
563 print_hf_line (context, cr, sheet, pinfo->header,
564 FALSE, width, pi->hfi);
565 cairo_restore (cr);
568 /* printing footer */
570 if (edge_to_above_footer > footer) {
571 cairo_save (cr);
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,
574 pi->hfi);
575 cairo_restore (cr);
578 /* setting up content area */
579 cairo_save (cr);
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
585 : NULL;
586 if (so) {
587 cairo_scale (cr, px, py);
588 sheet_object_draw_cairo_sized (so, cr, width, height);
590 } else {
592 if (pinfo->center_horizontally == 1 || pinfo->center_vertically == 1) {
593 double shift_x = 0;
594 double shift_y = 0;
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) {
607 cairo_save (cr);
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);
616 cairo_restore (cr);
617 cairo_save (cr);
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);
626 cairo_restore (cr);
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) {
641 GnmRange r;
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);
644 cairo_save (cr);
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);
649 cairo_restore (cr);
650 cairo_translate (cr, 0, rep_row_height );
653 /* printing repeated cols */
655 if (gsr->n_rep_cols > 0) {
656 GnmRange r;
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);
670 cairo_restore (cr);
671 return 1;
675 * Computes number of rows or columns that fit in @usable starting
676 * at index @start and limited to index @end
678 static int
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 */
684 int idx, count = 0;
686 for (idx = start; idx <= end; idx++, count++) {
687 ColRowInfo const *info = (*get_info) (sheet, idx);
688 if (info->visible) {
689 size_pts += info->size_pts;
690 if (size_pts > usable)
691 break;
695 /* FIXME : Find a way to inform the user that one of the rows/cols does
696 * not fit on a page
699 if (count ==0) {
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! */
703 return 1;
706 return count;
709 static void
710 adjust_repetition (Sheet const *sheet,
711 gint i,
712 gint first_rep,
713 gint n_rep,
714 gdouble repeating,
715 gint *first_rep_used,
716 gint *n_rep_used,
717 gdouble *repeating_used,
718 double (sheet_get_distance_pts) (Sheet const *sheet, int from, int to))
720 if (i > first_rep) {
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);
726 } else {
727 *repeating_used = repeating;
728 *n_rep_used = n_rep;
733 static gint
734 paginate (GArray *paginationInfo,
735 Sheet const *sheet,
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)
742 int rc = start;
743 gint n_rep = 0, first_rep = 0;
744 gdouble repeating = 0.;
745 gint page_count = 0;
747 if (repeat) {
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);
753 while (rc <= end) {
754 gint n_end;
756 n_end = gnm_page_breaks_get_next_manual_break (pb, rc) - 1;
757 if (n_end < rc)
758 n_end = end;
760 while (rc <= n_end) {
761 int count;
763 gdouble repeating_used = 0.;
764 gint n_rep_used = 0, first_rep_used = 0;
766 adjust_repetition (sheet, rc,
767 first_rep, n_rep,
768 repeating,
769 &first_rep_used, &n_rep_used,
770 &repeating_used,
771 sheet_get_distance_pts);
773 count = compute_group (sheet, rc, n_end,
774 usable - repeating_used,
775 get_info);
777 if (paginationInfo) {
778 PaginationInfo item;
779 item.rc = rc;
780 item.count = count;
781 item.first_rep = first_rep_used;
782 item.n_rep = n_rep_used;
783 g_array_append_val (paginationInfo, item);
785 page_count++;
787 rc += count;
788 if (store_breaks && (rc < n_end))
789 gnm_page_breaks_set_break (pb, rc, GNM_PAGE_BREAK_AUTO);
793 return page_count;
796 /* computer_scale_fit_to
797 * Computes the scaling needed to fit all the rows or columns into the @usable
798 * area.
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.
804 static double
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)
812 double max_p, min_p;
813 gint max_pages;
814 double extent;
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. */
824 if (pages <= 0)
825 return max_percent;
827 /* We can handle a single page easily: */
828 if (pages == 1) {
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)
846 return max_p;
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)
868 max_p = cur_p;
869 else
870 min_p = cur_p;
873 return min_p;
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)))
879 static void
880 compute_sheet_pages_add_sheet (PrintingInstance * pi, Sheet const *sheet,
881 gboolean selection,
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);
892 static Sheet *
893 print_get_sheet (PrintingInstance *pi, guint page_no)
895 GList *l;
897 for (l = pi->gnmSheets; l != NULL; l = l->next) {
898 SheetPrintInfo *spi = l->data;
899 if (spi->pages > page_no)
900 return spi->sheet;
901 else
902 page_no -= spi->pages;
905 return NULL;
908 static SheetPageRange *
909 print_get_sheet_page_range (PrintingInstance *pi, guint page_no)
911 GList *l;
913 for (l = pi->gnmSheets; l != NULL; l = l->next) {
914 SheetPrintInfo *spi = l->data;
915 if (spi->pages > page_no) {
916 SheetPageRange *gsr;
917 guint col, row;
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;
924 } else {
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;
943 gsr->sheet = sheet;
944 return gsr;
945 } else
946 page_no -= spi->pages;
949 return NULL;
953 return TRUE in case of trouble
956 static gboolean
957 compute_sheet_pages (GtkPrintContext *context,
958 PrintingInstance * pi,
959 SheetPrintInfo *spi)
961 Sheet *sheet = spi->sheet;
962 GnmPrintInformation *pinfo = sheet->print_info;
963 GnmRange r;
964 GnmRange const *selection_range;
965 GnmRange print_area;
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;
970 gdouble px, py;
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)
993 return TRUE;
994 if (spi->ignore_printarea) {
995 print_area = *selection_range;
996 } else {
997 if (!range_intersection (&r, selection_range, &print_area))
998 return FALSE;
999 print_area = r;
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));
1022 else
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));
1027 else
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! */
1035 gdouble pxy;
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.,
1041 col_header_height,
1042 repeat_top_use,
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,
1049 row_header_width,
1050 repeat_left_use,
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.;
1061 if (px <= 0.)
1062 px = 1.;
1063 if (py <= 0.)
1064 py = 1.;
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;
1084 return FALSE;
1088 * Computes the pages that will be output by a specific
1089 * print request.
1091 static void
1092 compute_pages (G_GNUC_UNUSED GtkPrintOperation *operation,
1093 PrintingInstance * pi)
1095 Workbook *wb = pi->wb;
1096 guint i;
1097 guint n;
1098 guint ct;
1099 PrintRange pr = pi->pr;
1100 guint from = pi->from;
1101 guint to = pi->to;
1103 switch (pr) {
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);
1108 break;
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)
1114 continue;
1115 if (!sheet_is_visible(sheet))
1116 continue;
1117 compute_sheet_pages_add_sheet (pi, sheet,
1118 FALSE, FALSE);
1120 break;
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)
1126 continue;
1127 compute_sheet_pages_add_sheet (pi, sheet,
1128 FALSE, FALSE);
1130 break;
1131 case GNM_PRINT_SHEET_RANGE:
1132 if (from > to)
1133 break;
1134 n = workbook_sheet_count (wb);
1135 ct = 0;
1136 for (i = 0; i < n; i++){
1137 Sheet *sheet = workbook_sheet_by_index (wb, i);
1138 if (sheet_is_visible(sheet))
1139 ct++;
1140 else
1141 continue;
1142 if (sheet->print_info->do_not_print)
1143 continue;
1144 if ((ct >= from) && (ct <= to))
1145 compute_sheet_pages_add_sheet (pi, sheet,
1146 FALSE, FALSE);
1148 break;
1149 case GNM_PRINT_SHEET_SELECTION:
1150 compute_sheet_pages_add_sheet (pi, pi->sheet, TRUE, FALSE);
1151 break;
1152 case GNM_PRINT_IGNORE_PRINTAREA:
1153 compute_sheet_pages_add_sheet (pi, pi->sheet, FALSE, TRUE);
1154 break;
1155 case GNM_PRINT_SHEET_SELECTION_IGNORE_PRINTAREA:
1156 compute_sheet_pages_add_sheet (pi, pi->sheet, TRUE, TRUE);
1157 break;
1159 return;
1162 #if 0
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 */
1172 pj->start_page = 0;
1173 pj->end_page = workbook_sheet_count (sheet->workbook) - 1;
1174 pj->range = range;
1175 pj->sorted_print = TRUE;
1176 pj->is_preview = preview;
1177 pj->current_output_sheet = 0;
1180 * Setup render info
1182 pj->render_info = gnm_print_hf_render_info_new ();
1183 pj->render_info->sheet = sheet;
1184 pj->render_info->page = 1;
1186 return pj;
1189 static void
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);
1198 g_free (pj);
1201 #endif
1203 static gboolean
1204 gnm_paginate_cb (GtkPrintOperation *operation,
1205 GtkPrintContext *context,
1206 gpointer user_data)
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) {
1220 GList *l;
1221 gint n_pages = 0;
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) {
1229 int i, count = 0;
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),
1237 count++;
1238 if (count > 1000)
1239 break;
1241 if (count > 1000 && !go_gtk_query_yes_no
1242 (pi->progress != NULL ?
1243 GTK_WINDOW (pi->progress) : wbcg_toplevel (WBC_GTK (pi->wbc)),
1244 FALSE, "%s",
1245 _("You have chosen more than 1000 pages to preview. "
1246 "This may take a long time. "
1247 "Do you really want to proceed?")))
1248 n_pages = 0;
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);
1258 return TRUE;
1261 if (compute_sheet_pages (context, pi, spi)) {
1262 gtk_print_operation_cancel (operation);
1263 return TRUE;
1266 return FALSE;
1269 static void
1270 cb_progress_response (G_GNUC_UNUSED GtkDialog *dialog,
1271 G_GNUC_UNUSED gint response_id,
1272 PrintingInstance *pi)
1274 pi->cancel = TRUE;
1277 static gboolean
1278 cb_progress_delete (G_GNUC_UNUSED GtkWidget *widget,
1279 G_GNUC_UNUSED GdkEvent *event,
1280 PrintingInstance *pi)
1282 pi->cancel = TRUE;
1283 return TRUE;
1286 static gboolean
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,
1291 gpointer user_data)
1293 PrintingInstance * pi = (PrintingInstance *) user_data;
1294 pi->preview = TRUE;
1296 return FALSE;
1299 static void
1300 gnm_begin_print_cb (GtkPrintOperation *operation,
1301 G_GNUC_UNUSED GtkPrintContext *context,
1302 gpointer user_data)
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,
1314 pi->from);
1315 gtk_print_settings_set_int
1316 (settings, GNUMERIC_PRINT_SETTING_PRINT_TO_SHEET_KEY,
1317 pi->to);
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)),
1326 GTK_DIALOG_MODAL |
1327 GTK_DIALOG_DESTROY_WITH_PARENT,
1328 GTK_MESSAGE_INFO,
1329 GTK_BUTTONS_CANCEL,
1330 "%s", /* please clang */
1331 pi->preview ?
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);
1344 static void
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");
1353 static void
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);
1368 static void
1369 gnm_request_page_setup_cb (GtkPrintOperation *operation,
1370 G_GNUC_UNUSED GtkPrintContext *context,
1371 gint page_nr,
1372 GtkPageSetup *setup,
1373 gpointer user_data)
1375 PrintingInstance * pi = (PrintingInstance *) user_data;
1376 Sheet *sheet;
1377 GtkPrintSettings* settings = gtk_print_operation_get_print_settings
1378 (operation);
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"); */
1386 return;
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);
1396 static void
1397 gnm_draw_page_cb (GtkPrintOperation *operation,
1398 GtkPrintContext *context,
1399 gint page_nr,
1400 gpointer user_data)
1403 PrintingInstance * pi = (PrintingInstance *) user_data;
1404 SheetPageRange * gsr;
1406 if (gnm_debug_flag ("print"))
1407 g_printerr ("draw-page %d\n", page_nr);
1409 if (pi->cancel) {
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);
1413 return;
1416 gsr = print_get_sheet_page_range (pi, page_nr);
1417 if (gsr) {
1418 if (pi->progress) {
1419 char *text;
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);
1425 else
1426 text = g_strdup_printf
1427 (pi->preview ?
1428 ngettext("Creating preview of page %3d of %3d page",
1429 "Creating preview of page %3d of %3d pages",
1430 pi->hfi->pages)
1431 : ngettext("Printing page %3d of %3d page",
1432 "Printing page %3d of %3d pages",
1433 pi->hfi->pages),
1434 page_nr, pi->hfi->pages);
1435 g_object_set (G_OBJECT (pi->progress), "text", text, NULL);
1436 g_free (text);
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);
1447 g_free (gsr);
1451 static void
1452 widget_button_cb (GtkToggleButton *togglebutton, GtkWidget *check)
1454 gtk_widget_set_sensitive (check, gtk_toggle_button_get_active (togglebutton));
1457 static guint
1458 workbook_visible_sheet_count (Workbook *wb)
1460 guint i;
1461 guint n = workbook_sheet_count (wb);
1462 guint count = 0;
1464 for (i = 0; i < n; i++) {
1465 Sheet *sheet = workbook_sheet_by_index (wb, i);
1466 if (sheet_is_visible(sheet))
1467 count++;
1469 return count;
1472 static GObject*
1473 gnm_create_widget_cb (GtkPrintOperation *operation, gpointer user_data)
1475 PrintingInstance * pi = (PrintingInstance *) user_data;
1476 GtkWidget *grid;
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 ();
1490 g_object_set (grid,
1491 "column-spacing", 12,
1492 "row-spacing", 6,
1493 "border-width", 6,
1494 NULL);
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,
1504 "hexpand", TRUE,
1505 "margin-left", 24,
1506 NULL);
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,
1522 "hexpand", TRUE,
1523 "margin-left", 24,
1524 NULL);
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,
1530 "hexpand", TRUE,
1531 "margin-left", 24,
1532 NULL);
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,
1537 "hexpand", TRUE,
1538 "margin-left", 24,
1539 NULL);
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);
1585 if (settings) {
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);
1591 /* no break */
1592 case GNM_PRINT_SHEET_SELECTION:
1593 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_selection), TRUE);
1594 /* no break */
1595 case GNM_PRINT_ACTIVE_SHEET:
1596 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_selected_sheet), TRUE);
1597 break;
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);
1601 break;
1602 case GNM_PRINT_SHEET_RANGE:
1603 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_spec_sheets), TRUE);
1604 break;
1605 case GNM_PRINT_ALL_SHEETS_INCLUDING_HIDDEN:
1606 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_print_hidden_sheets), TRUE);
1607 /* no break */
1608 case GNM_PRINT_ALL_SHEETS:
1609 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button_all_sheets), TRUE);
1610 break;
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,
1616 1));
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,
1620 n_sheets));
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,
1624 0));
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);
1651 static void
1652 gnm_custom_widget_apply_cb (GtkPrintOperation *operation,
1653 G_GNUC_UNUSED GtkWidget *widget,
1654 gpointer user_data)
1656 PrintingInstance * pi = (PrintingInstance *) user_data;
1657 GtkPrintSettings * settings;
1658 PrintRange pr = GNM_PRINT_ACTIVE_SHEET;
1659 guint from, to;
1660 gboolean ignore_pb;
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,
1671 from);
1672 gtk_print_settings_set_int (settings,
1673 GNUMERIC_PRINT_SETTING_PRINT_TO_SHEET_KEY,
1674 to);
1675 pi->from = from;
1676 pi->to = to;
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;
1681 else
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;
1692 else if (selection)
1693 pr = GNM_PRINT_SHEET_SELECTION;
1694 else if (ignore_printarea)
1695 pr = GNM_PRINT_IGNORE_PRINTAREA;
1696 else
1697 pr = GNM_PRINT_ACTIVE_SHEET;
1700 gtk_print_settings_set_int (settings,
1701 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY, pr);
1703 pi->pr = 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,
1707 ignore_pb);
1708 pi->ignore_pb = ignore_pb;
1711 static void
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);
1720 static gchar *
1721 gnm_print_uri_change_extension (char const *uri, GtkPrintSettings* settings)
1723 const gchar *ext = gtk_print_settings_get
1724 (settings,
1725 GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
1726 gchar *base;
1727 gchar *used_ext;
1728 gint strip;
1729 gchar *res;
1730 gint uri_len = strlen(uri);
1732 if (ext == NULL) {
1733 ext = "pdf";
1734 gtk_print_settings_set (settings,
1735 GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT,
1736 ext);
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);
1747 return res;
1750 void
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};
1769 GODoc *doc;
1770 gchar *output_uri = NULL;
1771 gchar const *saved_uri = NULL;
1773 #ifdef PREVIEW_VIA_PDF
1774 preview_via_pdf = preview;
1775 #endif
1777 g_return_if_fail (sheet != NULL && sheet->workbook != NULL);
1779 if (preview)
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;
1789 pi->sheet = sheet;
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;
1797 else
1798 default_range = pr_translator[dr];
1800 gtk_print_settings_set_int (settings,
1801 GNUMERIC_PRINT_SETTING_PRINTRANGE_KEY,
1802 default_range);
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 */
1808 /* reasonable */
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,
1813 settings);
1814 else
1815 saved_uri = NULL;
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,
1819 settings);
1820 if (output_uri != NULL) {
1821 gtk_print_settings_set (settings,
1822 GTK_PRINT_SETTINGS_OUTPUT_URI,
1823 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);
1832 if (page_setup)
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) {
1849 GError *err = NULL;
1851 tmp_file_fd = g_file_open_tmp ("gnmXXXXXX.pdf",
1852 &tmp_file_name, &err);
1853 if (err) {
1854 if (export_dst)
1855 gsf_output_set_error (export_dst, 0,
1856 "%s", err->message);
1857 else {
1858 char *text = g_strdup_printf
1859 (_("Failed to create temporary file for printing: %s"),
1860 err->message);
1861 go_cmd_context_error_export
1862 (GO_CMD_CONTEXT (wbc), text);
1863 g_free (text);
1865 g_error_free (err);
1866 goto out;
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);
1872 } else {
1873 action = preview
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);
1884 switch (res) {
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,
1896 settings);
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);
1904 break;
1905 case GTK_PRINT_OPERATION_RESULT_CANCEL:
1906 break;
1907 case GTK_PRINT_OPERATION_RESULT_ERROR:
1908 break;
1909 case GTK_PRINT_OPERATION_RESULT_IN_PROGRESS:
1910 /* This can only happen if we were allowing asynchronous operation */
1911 break;
1912 default: ;
1914 printing_instance_delete (pi);
1916 if (preview_via_pdf) {
1917 #ifdef G_OS_WIN32
1918 /* For some reason the general code doesn't work for me.
1919 Be brutal, even if this might not work for non-ASCII
1920 filenames. */
1921 int res = (int)ShellExecute (NULL, "open",
1922 tmp_file_name,
1923 NULL,
1924 NULL,
1925 SW_SHOW);
1926 if (gnm_debug_flag ("preview")) {
1927 g_printerr ("tmp_file_name=%s\n", tmp_file_name);
1928 g_printerr ("res=%d\n", res);
1930 #else
1931 GdkScreen *screen = parent
1932 ? gtk_widget_get_screen (GTK_WIDGET (parent))
1933 : NULL;
1934 char *url = go_filename_to_uri (tmp_file_name);
1935 go_gtk_url_show (url, screen);
1936 g_free (url);
1937 #endif
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];
1949 gssize bytes_read;
1951 if (lseek (tmp_file_fd, 0, SEEK_SET) < 0)
1952 bytes_read = -1;
1953 else {
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));
1967 out:
1968 if (tmp_file_fd >= 0)
1969 close (tmp_file_fd);
1970 cb_delete_and_free (tmp_file_name);
1972 g_object_unref (print);
1975 static void
1976 gnm_draw_so_page_cb (G_GNUC_UNUSED GtkPrintOperation *operation,
1977 GtkPrintContext *context,
1978 G_GNUC_UNUSED gint page_nr,
1979 gpointer user_data)
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);
1986 cairo_save (cr);
1987 cairo_translate (cr, 0, 0);
1988 sheet_object_draw_cairo (so, (gpointer)cr, sheet->text_is_rtl);
1989 cairo_restore (cr);
1993 * gnm_print_so:
1994 * @wbc:
1995 * @sos: (element-type SheetObject) (transfer none):
1996 * @export_dst:
1998 void
1999 gnm_print_so (WorkbookControl *wbc, GPtrArray *sos,
2000 GsfOutput *export_dst)
2002 GtkPrintOperation *print;
2003 GtkPageSetup *page_setup;
2004 GtkPrintSettings* settings;
2005 Sheet *sheet;
2006 GtkWindow *parent = NULL;
2007 GtkPrintOperationAction action;
2008 gchar *tmp_file_name = NULL;
2009 int tmp_file_fd = -1;
2010 SheetObject *so;
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);
2030 if (page_setup)
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);
2041 if (export_dst) {
2042 GError *err = NULL;
2044 tmp_file_fd = g_file_open_tmp ("gnmXXXXXX.pdf",
2045 &tmp_file_name, &err);
2046 if (err) {
2047 gsf_output_set_error (export_dst, 0,
2048 "%s", err->message);
2049 g_error_free (err);
2050 if (tmp_file_fd >= 0)
2051 close (tmp_file_fd);
2052 cb_delete_and_free (tmp_file_name);
2054 g_object_unref (print);
2055 return;
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);
2060 } else {
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];
2069 gssize bytes_read;
2071 if (lseek (tmp_file_fd, 0, SEEK_SET) < 0)
2072 bytes_read = -1;
2073 else {
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);