2 * printing.c - this file is part of Geany, a fast and lightweight IDE
4 * Copyright 2007-2012 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5 * Copyright 2007-2012 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
6 * Copyright 2012 Colomban Wendling <ban(at)herbesfolles(dot)org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * GTK printing support
26 * (basic code layout were adopted from Sylpheed's printing implementation, thanks)
39 #include "highlighting.h"
40 #include "msgwindow.h"
41 #include "sciwrappers.h"
51 PrintingPrefs printing_prefs
;
54 /* document-related variables */
61 /* set in begin_print() to hold the time when printing was started to ensure all printed
62 * pages have the same date and time (in case of slow machines and many pages where rendering
63 * takes more than a second) */
65 PangoLayout
*layout
; /* commonly used layout object */
68 struct Sci_RangeToFormat fr
;
72 /* widget references for the custom widget in the print dialog */
75 GtkWidget
*check_print_linenumbers
;
76 GtkWidget
*check_print_pagenumbers
;
77 GtkWidget
*check_print_pageheader
;
78 GtkWidget
*check_print_basename
;
79 GtkWidget
*entry_print_dateformat
;
83 static GtkPrintSettings
*settings
= NULL
;
84 static GtkPageSetup
*page_setup
= NULL
;
88 /* creates a commonly used layout object from the given context for use in get_page_count and
90 static PangoLayout
*setup_pango_layout(GtkPrintContext
*context
, PangoFontDescription
*desc
)
94 layout
= gtk_print_context_create_pango_layout(context
);
95 pango_layout_set_wrap(layout
, PANGO_WRAP_WORD_CHAR
);
96 pango_layout_set_spacing(layout
, 0);
97 pango_layout_set_attributes(layout
, NULL
);
98 pango_layout_set_font_description(layout
, desc
);
104 static void get_text_dimensions(PangoLayout
*layout
, const gchar
*text
, gdouble
*width
, gdouble
*height
)
106 gint layout_w
, layout_h
;
108 pango_layout_set_text(layout
, text
, -1);
109 pango_layout_get_size(layout
, &layout_w
, &layout_h
);
112 gint default_w
= 50 * strlen(text
) * PANGO_SCALE
;
114 geany_debug("Invalid layout_w (%d). Falling back to default width (%d)",
115 layout_w
, default_w
);
116 layout_w
= default_w
;
120 gint default_h
= 100 * PANGO_SCALE
;
122 geany_debug("Invalid layout_h (%d). Falling back to default height (%d)",
123 layout_h
, default_h
);
124 layout_h
= default_h
;
128 *width
= (gdouble
)layout_w
/ PANGO_SCALE
;
130 *height
= (gdouble
)layout_h
/ PANGO_SCALE
;
134 static void add_page_header(DocInfo
*dinfo
, cairo_t
*cr
, gint width
, gint page_nr
)
136 gint ph_height
= dinfo
->line_height
* 3;
139 const gchar
*tmp_file_name
= DOC_FILENAME(dinfo
->doc
);
140 gchar
*file_name
= (printing_prefs
.page_header_basename
) ?
141 g_path_get_basename(tmp_file_name
) : g_strdup(tmp_file_name
);
142 PangoLayout
*layout
= dinfo
->layout
;
145 cairo_set_line_width(cr
, 0.3);
146 cairo_set_source_rgb(cr
, 0, 0, 0);
147 cairo_rectangle(cr
, 2, 2, width
- 4, ph_height
- 4);
150 /* width - 8: 2px between doc border and frame border, 2px between frame border and text
151 * and this on left and right side, so (2 + 2) * 2 */
152 pango_layout_set_width(layout
, (width
- 8) * PANGO_SCALE
);
153 pango_layout_set_ellipsize(layout
, PANGO_ELLIPSIZE_MIDDLE
);
155 data
= g_strdup_printf("<b>%s</b>", file_name
);
156 pango_layout_set_markup(layout
, data
, -1);
157 pango_layout_set_alignment(layout
, PANGO_ALIGN_LEFT
);
158 cairo_move_to(cr
, 4, dinfo
->line_height
* 0.5);
159 pango_cairo_show_layout(cr
, layout
);
163 data
= g_strdup_printf(_("<b>Page %d of %d</b>"), page_nr
+ 1, dinfo
->pages
->len
);
164 pango_layout_set_markup(layout
, data
, -1);
165 pango_layout_set_alignment(layout
, PANGO_ALIGN_LEFT
);
166 cairo_move_to(cr
, 4, dinfo
->line_height
* 1.5);
167 pango_cairo_show_layout(cr
, layout
);
170 datetime
= utils_get_date_time(printing_prefs
.page_header_datefmt
, &(dinfo
->print_time
));
171 if (G_LIKELY(!EMPTY(datetime
)))
173 data
= g_strdup_printf("<b>%s</b>", datetime
);
174 pango_layout_set_markup(layout
, data
, -1);
175 pango_layout_set_alignment(layout
, PANGO_ALIGN_RIGHT
);
176 cairo_move_to(cr
, 2, dinfo
->line_height
* 1.5);
177 pango_cairo_show_layout(cr
, layout
);
182 /* reset layout and re-position cairo context */
183 pango_layout_set_alignment(layout
, PANGO_ALIGN_LEFT
);
184 pango_layout_set_ellipsize(layout
, PANGO_ELLIPSIZE_NONE
);
185 pango_layout_set_justify(layout
, FALSE
);
186 pango_layout_set_width(layout
, width
* PANGO_SCALE
);
187 cairo_move_to(cr
, 0, dinfo
->line_height
* 3);
191 static void custom_widget_apply(GtkPrintOperation
*operation
, GtkWidget
*widget
, gpointer user_data
)
193 PrintWidgets
*w
= user_data
;
195 printing_prefs
.print_line_numbers
=
196 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w
->check_print_linenumbers
));
198 printing_prefs
.print_page_numbers
=
199 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w
->check_print_pagenumbers
));
201 printing_prefs
.print_page_header
=
202 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w
->check_print_pageheader
));
204 printing_prefs
.page_header_basename
=
205 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w
->check_print_basename
));
207 g_free(printing_prefs
.page_header_datefmt
);
208 printing_prefs
.page_header_datefmt
=
209 g_strdup(gtk_entry_get_text(GTK_ENTRY(w
->entry_print_dateformat
)));
213 static void on_page_header_toggled(GtkToggleButton
*togglebutton
, gpointer user_data
)
215 gboolean sens
= gtk_toggle_button_get_active(togglebutton
);
216 PrintWidgets
*w
= user_data
;
218 gtk_widget_set_sensitive(w
->check_print_basename
, sens
);
219 gtk_widget_set_sensitive(w
->entry_print_dateformat
, sens
);
223 static GtkWidget
*create_custom_widget(GtkPrintOperation
*operation
, gpointer user_data
)
224 { /* copied from interface.c */
227 GtkWidget
*alignment36
;
231 PrintWidgets
*w
= user_data
;
233 gtk_print_operation_set_custom_tab_label(operation
, _("Document Setup"));
235 page
= gtk_vbox_new(FALSE
, 0);
236 gtk_container_set_border_width(GTK_CONTAINER(page
), 5);
238 w
->check_print_linenumbers
= gtk_check_button_new_with_mnemonic(_("Print line numbers"));
239 gtk_box_pack_start(GTK_BOX(page
), w
->check_print_linenumbers
, FALSE
, FALSE
, 0);
240 gtk_widget_set_tooltip_text(w
->check_print_linenumbers
, _("Add line numbers to the printed page"));
241 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w
->check_print_linenumbers
), printing_prefs
.print_line_numbers
);
243 w
->check_print_pagenumbers
= gtk_check_button_new_with_mnemonic(_("Print page numbers"));
244 gtk_box_pack_start(GTK_BOX(page
), w
->check_print_pagenumbers
, FALSE
, FALSE
, 0);
245 gtk_widget_set_tooltip_text(w
->check_print_pagenumbers
, _("Add page numbers at the bottom of each page. It takes 2 lines of the page."));
246 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w
->check_print_pagenumbers
), printing_prefs
.print_page_numbers
);
248 w
->check_print_pageheader
= gtk_check_button_new_with_mnemonic(_("Print page header"));
249 gtk_box_pack_start(GTK_BOX(page
), w
->check_print_pageheader
, FALSE
, FALSE
, 0);
250 gtk_widget_set_tooltip_text(w
->check_print_pageheader
, _("Add a little header to every page containing the page number, the filename and the current date (see below). It takes 3 lines of the page."));
251 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w
->check_print_pageheader
), printing_prefs
.print_page_header
);
252 g_signal_connect(w
->check_print_pageheader
, "toggled", G_CALLBACK(on_page_header_toggled
), w
);
254 frame33
= gtk_frame_new(NULL
);
255 gtk_box_pack_start(GTK_BOX(page
), frame33
, FALSE
, FALSE
, 0);
256 gtk_frame_set_label_align(GTK_FRAME(frame33
), 0, 0);
257 gtk_frame_set_shadow_type(GTK_FRAME(frame33
), GTK_SHADOW_NONE
);
259 alignment36
= gtk_alignment_new(0, 0.5, 1, 1);
260 gtk_container_add(GTK_CONTAINER(frame33
), alignment36
);
261 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment36
), 0, 0, 12, 0);
263 vbox30
= gtk_vbox_new(FALSE
, 1);
264 gtk_container_add(GTK_CONTAINER(alignment36
), vbox30
);
266 w
->check_print_basename
= gtk_check_button_new_with_mnemonic(_("Use the basename of the printed file"));
267 gtk_box_pack_start(GTK_BOX(vbox30
), w
->check_print_basename
, FALSE
, FALSE
, 0);
268 gtk_widget_set_tooltip_text(w
->check_print_basename
, _("Print only the basename(without the path) of the printed file"));
269 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w
->check_print_basename
), printing_prefs
.page_header_basename
);
271 hbox10
= gtk_hbox_new(FALSE
, 5);
272 gtk_box_pack_start(GTK_BOX(vbox30
), hbox10
, TRUE
, TRUE
, 0);
274 label203
= gtk_label_new(_("Date format:"));
275 gtk_box_pack_start(GTK_BOX(hbox10
), label203
, FALSE
, FALSE
, 0);
277 w
->entry_print_dateformat
= gtk_entry_new();
278 ui_entry_add_clear_icon(GTK_ENTRY(w
->entry_print_dateformat
));
279 gtk_box_pack_start(GTK_BOX(hbox10
), w
->entry_print_dateformat
, TRUE
, TRUE
, 0);
280 gtk_widget_set_tooltip_text(w
->entry_print_dateformat
, _("Specify a format for the date and time stamp which is added to the page header on each page. You can use any conversion specifiers which can be used with the ANSI C strftime function."));
281 gtk_entry_set_text(GTK_ENTRY(w
->entry_print_dateformat
), printing_prefs
.page_header_datefmt
);
283 on_page_header_toggled(GTK_TOGGLE_BUTTON(w
->check_print_pageheader
), w
);
284 gtk_widget_show_all(page
);
289 static void end_print(GtkPrintOperation
*operation
, GtkPrintContext
*context
, gpointer user_data
)
291 DocInfo
*dinfo
= user_data
;
296 gtk_widget_hide(main_widgets
.progressbar
);
297 g_object_unref(dinfo
->sci
);
298 g_object_unref(dinfo
->layout
);
299 g_array_free(dinfo
->pages
, TRUE
);
303 static void setup_range(DocInfo
*dinfo
, GtkPrintContext
*ctx
)
305 dinfo
->fr
.hdc
= dinfo
->fr
.hdcTarget
= gtk_print_context_get_cairo_context(ctx
);
307 dinfo
->fr
.rcPage
.left
= 0;
308 dinfo
->fr
.rcPage
.top
= 0;
309 dinfo
->fr
.rcPage
.right
= gtk_print_context_get_width(ctx
);
310 dinfo
->fr
.rcPage
.bottom
= gtk_print_context_get_height(ctx
);
312 dinfo
->fr
.rc
.left
= dinfo
->fr
.rcPage
.left
;
313 dinfo
->fr
.rc
.top
= dinfo
->fr
.rcPage
.top
;
314 dinfo
->fr
.rc
.right
= dinfo
->fr
.rcPage
.right
;
315 dinfo
->fr
.rc
.bottom
= dinfo
->fr
.rcPage
.bottom
;
317 if (printing_prefs
.print_page_header
)
318 dinfo
->fr
.rc
.top
+= dinfo
->line_height
* 3; /* header height */
319 if (printing_prefs
.print_page_numbers
)
320 dinfo
->fr
.rc
.bottom
-= dinfo
->line_height
* 1; /* footer height */
322 dinfo
->fr
.rcPage
.left
/= dinfo
->sci_scale
;
323 dinfo
->fr
.rcPage
.top
/= dinfo
->sci_scale
;
324 dinfo
->fr
.rcPage
.right
/= dinfo
->sci_scale
;
325 dinfo
->fr
.rcPage
.bottom
/= dinfo
->sci_scale
;
326 dinfo
->fr
.rc
.left
/= dinfo
->sci_scale
;
327 dinfo
->fr
.rc
.top
/= dinfo
->sci_scale
;
328 dinfo
->fr
.rc
.right
/= dinfo
->sci_scale
;
329 dinfo
->fr
.rc
.bottom
/= dinfo
->sci_scale
;
331 dinfo
->fr
.chrg
.cpMin
= 0;
332 dinfo
->fr
.chrg
.cpMax
= sci_get_length(dinfo
->sci
);
336 static void begin_print(GtkPrintOperation
*operation
, GtkPrintContext
*context
, gpointer user_data
)
338 DocInfo
*dinfo
= user_data
;
339 PangoContext
*pango_ctx
, *widget_pango_ctx
;
340 PangoFontDescription
*desc
;
341 gdouble pango_res
, widget_res
;
346 gtk_widget_show(main_widgets
.progressbar
);
348 /* init dinfo fields */
350 /* setup printing scintilla object */
351 dinfo
->sci
= editor_create_widget(dinfo
->doc
->editor
);
352 /* since we won't add the widget to any container, assume it's ownership */
353 g_object_ref_sink(dinfo
->sci
);
354 scintilla_send_message(dinfo
->sci
, SCI_SETDOCPOINTER
, 0,
355 scintilla_send_message(dinfo
->doc
->editor
->sci
, SCI_GETDOCPOINTER
, 0, 0));
356 highlighting_set_styles(dinfo
->sci
, dinfo
->doc
->file_type
);
357 sci_set_line_numbers(dinfo
->sci
, printing_prefs
.print_line_numbers
);
358 scintilla_send_message(dinfo
->sci
, SCI_SETVIEWWS
, SCWS_INVISIBLE
, 0);
359 scintilla_send_message(dinfo
->sci
, SCI_SETVIEWEOL
, FALSE
, 0);
360 scintilla_send_message(dinfo
->sci
, SCI_SETEDGEMODE
, EDGE_NONE
, 0);
361 scintilla_send_message(dinfo
->sci
, SCI_SETPRINTCOLOURMODE
, SC_PRINT_COLOURONWHITE
, 0);
363 /* Scintilla doesn't respect the context resolution, so we'll scale ourselves.
364 * Actually Scintilla simply doesn't know about the resolution since it creates its own
365 * Pango context out of the Cairo target, and the resolution is in the GtkPrintOperation's
367 pango_ctx
= gtk_print_context_create_pango_context(context
);
368 pango_res
= pango_cairo_context_get_resolution(pango_ctx
);
369 g_object_unref(pango_ctx
);
370 widget_pango_ctx
= gtk_widget_get_pango_context(GTK_WIDGET(dinfo
->sci
));
371 widget_res
= pango_cairo_context_get_resolution(widget_pango_ctx
);
372 /* On Windows, for some reason the widget's resolution is -1, so follow
373 * Pango docs and peek the font map's one. */
376 widget_res
= pango_cairo_font_map_get_resolution(
377 (PangoCairoFontMap
*) pango_context_get_font_map(widget_pango_ctx
));
379 dinfo
->sci_scale
= pango_res
/ widget_res
;
381 dinfo
->pages
= g_array_new(FALSE
, FALSE
, sizeof(gint
));
383 dinfo
->print_time
= time(NULL
);
384 /* create a PangoLayout to be commonly used in add_page_header() and draw_page() */
385 desc
= pango_font_description_from_string(interface_prefs
.editor_font
);
386 dinfo
->layout
= setup_pango_layout(context
, desc
);
387 pango_font_description_free(desc
);
388 get_text_dimensions(dinfo
->layout
, "|XMfjgq_" /* reasonably representative character set */,
389 NULL
, &dinfo
->line_height
);
390 get_text_dimensions(dinfo
->layout
, "99999 " /* Scintilla resets the margin to the width of "99999" when printing */,
391 &dinfo
->margin_width
, NULL
);
392 /* setup dinfo->fr */
393 setup_range(dinfo
, context
);
397 static gint
format_range(DocInfo
*dinfo
, gboolean draw
)
401 cairo_save(dinfo
->fr
.hdc
);
402 cairo_scale(dinfo
->fr
.hdc
, dinfo
->sci_scale
, dinfo
->sci_scale
);
403 pos
= (gint
) scintilla_send_message(dinfo
->sci
, SCI_FORMATRANGE
, draw
, (sptr_t
) &dinfo
->fr
);
404 cairo_restore(dinfo
->fr
.hdc
);
410 static gboolean
paginate(GtkPrintOperation
*operation
, GtkPrintContext
*context
, gpointer user_data
)
412 DocInfo
*dinfo
= user_data
;
414 /* for whatever reason we get called one more time after we returned TRUE, so avoid adding
415 * an empty page at the end */
416 if (dinfo
->fr
.chrg
.cpMin
>= dinfo
->fr
.chrg
.cpMax
)
419 gtk_progress_bar_pulse(GTK_PROGRESS_BAR(main_widgets
.progressbar
));
420 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets
.progressbar
), _("Paginating"));
422 g_array_append_val(dinfo
->pages
, dinfo
->fr
.chrg
.cpMin
);
423 dinfo
->fr
.chrg
.cpMin
= format_range(dinfo
, FALSE
);
425 gtk_print_operation_set_n_pages(operation
, dinfo
->pages
->len
);
427 return dinfo
->fr
.chrg
.cpMin
>= dinfo
->fr
.chrg
.cpMax
;
431 static void draw_page(GtkPrintOperation
*operation
, GtkPrintContext
*context
,
432 gint page_nr
, gpointer user_data
)
434 DocInfo
*dinfo
= user_data
;
436 gdouble width
, height
;
438 g_return_if_fail(dinfo
!= NULL
);
439 g_return_if_fail((guint
)page_nr
< dinfo
->pages
->len
);
441 if (dinfo
->pages
->len
> 0)
443 gdouble fraction
= (page_nr
+ 1) / (gdouble
) dinfo
->pages
->len
;
444 gchar
*text
= g_strdup_printf(_("Page %d of %d"), page_nr
+ 1, dinfo
->pages
->len
);
445 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(main_widgets
.progressbar
), fraction
);
446 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(main_widgets
.progressbar
), text
);
450 cr
= gtk_print_context_get_cairo_context(context
);
451 width
= gtk_print_context_get_width(context
);
452 height
= gtk_print_context_get_height(context
);
454 if (printing_prefs
.print_page_header
)
455 add_page_header(dinfo
, cr
, width
, page_nr
);
457 dinfo
->fr
.chrg
.cpMin
= g_array_index(dinfo
->pages
, gint
, page_nr
);
458 if ((guint
)page_nr
+ 1 < dinfo
->pages
->len
)
459 dinfo
->fr
.chrg
.cpMax
= g_array_index(dinfo
->pages
, gint
, page_nr
+ 1) - 1;
460 else /* it's the last page, print 'til the end */
461 dinfo
->fr
.chrg
.cpMax
= sci_get_length(dinfo
->sci
);
463 format_range(dinfo
, TRUE
);
466 cairo_set_source_rgb(cr
, 0, 0, 0);
468 if (printing_prefs
.print_line_numbers
)
469 { /* print a thin line between the line number margin and the data */
470 gdouble y1
= dinfo
->fr
.rc
.top
* dinfo
->sci_scale
;
471 gdouble y2
= dinfo
->fr
.rc
.bottom
* dinfo
->sci_scale
;
472 gdouble x
= dinfo
->fr
.rc
.left
* dinfo
->sci_scale
+ dinfo
->margin_width
;
474 if (printing_prefs
.print_page_header
)
475 y1
-= 2 - 0.3; /* to connect the line number line to the page header frame,
476 * 2 is the border, and 0.3 the line width */
478 cairo_set_line_width(cr
, 0.3);
479 cairo_move_to(cr
, x
, y1
);
480 cairo_line_to(cr
, x
, y2
);
484 if (printing_prefs
.print_page_numbers
)
486 gchar
*line
= g_strdup_printf("<small>- %d -</small>", page_nr
+ 1);
487 pango_layout_set_markup(dinfo
->layout
, line
, -1);
488 pango_layout_set_alignment(dinfo
->layout
, PANGO_ALIGN_CENTER
);
489 cairo_move_to(cr
, 0, height
- dinfo
->line_height
);
490 pango_cairo_show_layout(cr
, dinfo
->layout
);
496 static void status_changed(GtkPrintOperation
*op
, gpointer data
)
498 gchar
*filename
= (data
!= NULL
) ? data
: GEANY_STRING_UNTITLED
;
499 if (gtk_print_operation_get_status(op
) == GTK_PRINT_STATUS_FINISHED_ABORTED
)
500 msgwin_status_add(_("Did not send document %s to the printing subsystem."), filename
);
501 else if (gtk_print_operation_get_status(op
) == GTK_PRINT_STATUS_FINISHED
)
502 msgwin_status_add(_("Document %s was sent to the printing subsystem."), filename
);
506 static void printing_print_gtk(GeanyDocument
*doc
)
508 GtkPrintOperation
*op
;
509 GtkPrintOperationResult res
= GTK_PRINT_OPERATION_RESULT_ERROR
;
510 GError
*error
= NULL
;
511 static const DocInfo dinfo0
;
512 DocInfo dinfo
= dinfo0
;
513 PrintWidgets
*widgets
;
515 /** TODO check for monospace font, detect the widest character in the font and
516 * use it at font_width */
518 widgets
= g_new0(PrintWidgets
, 1);
519 /* all other fields are initialised in begin_print() */
522 op
= gtk_print_operation_new();
524 gtk_print_operation_set_unit(op
, GTK_UNIT_POINTS
);
525 gtk_print_operation_set_show_progress(op
, TRUE
);
526 #if GTK_CHECK_VERSION(2, 18, 0)
527 gtk_print_operation_set_embed_page_setup(op
, TRUE
);
530 g_signal_connect(op
, "begin-print", G_CALLBACK(begin_print
), &dinfo
);
531 g_signal_connect(op
, "end-print", G_CALLBACK(end_print
), &dinfo
);
532 g_signal_connect(op
, "paginate", G_CALLBACK(paginate
), &dinfo
);
533 g_signal_connect(op
, "draw-page", G_CALLBACK(draw_page
), &dinfo
);
534 g_signal_connect(op
, "status-changed", G_CALLBACK(status_changed
), doc
->file_name
);
535 g_signal_connect(op
, "create-custom-widget", G_CALLBACK(create_custom_widget
), widgets
);
536 g_signal_connect(op
, "custom-widget-apply", G_CALLBACK(custom_widget_apply
), widgets
);
538 if (settings
!= NULL
)
539 gtk_print_operation_set_print_settings(op
, settings
);
540 if (page_setup
!= NULL
)
541 gtk_print_operation_set_default_page_setup(op
, page_setup
);
543 res
= gtk_print_operation_run(
544 op
, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG
, GTK_WINDOW(main_widgets
.window
), &error
);
546 if (res
== GTK_PRINT_OPERATION_RESULT_APPLY
)
548 if (settings
!= NULL
)
549 g_object_unref(settings
);
550 settings
= g_object_ref(gtk_print_operation_get_print_settings(op
));
551 /* status message is printed in the status-changed handler */
553 else if (res
== GTK_PRINT_OPERATION_RESULT_ERROR
)
555 dialogs_show_msgbox(GTK_MESSAGE_ERROR
, _("Printing of %s failed (%s)."),
556 doc
->file_name
, error
->message
);
565 void printing_page_setup_gtk(void)
567 GtkPageSetup
*new_page_setup
;
569 if (settings
== NULL
)
570 settings
= gtk_print_settings_new();
572 new_page_setup
= gtk_print_run_page_setup_dialog(
573 GTK_WINDOW(main_widgets
.window
), page_setup
, settings
);
575 if (page_setup
!= NULL
)
576 g_object_unref(page_setup
);
578 page_setup
= new_page_setup
;
582 /* simple file print using an external tool */
583 static void print_external(GeanyDocument
*doc
)
587 if (doc
->file_name
== NULL
)
590 if (EMPTY(printing_prefs
.external_print_cmd
))
592 dialogs_show_msgbox(GTK_MESSAGE_ERROR
,
593 _("Please set a print command in the preferences dialog first."));
597 cmdline
= g_strdup(printing_prefs
.external_print_cmd
);
598 utils_str_replace_all(&cmdline
, "%f", doc
->file_name
);
600 if (dialogs_show_question(
601 _("The file \"%s\" will be printed with the following command:\n\n%s"),
602 doc
->file_name
, cmdline
))
604 GError
*error
= NULL
;
607 gchar
*tmp_cmdline
= g_strdup(cmdline
);
609 /* /bin/sh -c emulates the system() call and makes complex commands possible
610 * but only needed on non-win32 systems due to the lack of win32's shell capabilities */
611 gchar
*tmp_cmdline
= g_strconcat("/bin/sh -c \"", cmdline
, "\"", NULL
);
614 if (! g_spawn_command_line_async(tmp_cmdline
, &error
))
616 dialogs_show_msgbox(GTK_MESSAGE_ERROR
,
617 _("Printing of \"%s\" failed (return code: %s)."),
618 doc
->file_name
, error
->message
);
623 msgwin_status_add(_("File %s printed."), doc
->file_name
);
631 void printing_print_doc(GeanyDocument
*doc
)
633 g_return_if_fail(DOC_VALID(doc
));
635 if (printing_prefs
.use_gtk_printing
)
636 printing_print_gtk(doc
);