2
* printing.c - this file is part of Geany, a fast and lightweight IDE
4
* Copyright 2007-2008 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
5
* Copyright 2007-2008 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
* $Id: printing.c 2287 2008-02-27 13:17:29Z eht16 $
26
* GTK 2.10 printing support
27
* (basic code layout were adopted from Sylpheed's printing implementation, thanks)
38
#include "sciwrappers.h"
40
#include "sciwrappers.h"
45
#include "msgwindow.h"
48
PrintingPrefs printing_prefs;
51
#if GTK_CHECK_VERSION(2, 10, 0)
54
#define ROTATE_RGB(color) \
55
(((color) & 0xFF0000) >> 16) + ((color) & 0x00FF00) + (((color) & 0x0000FF) << 16)
56
#define ADD_ATTR(l, a) \
57
pango_attr_list_insert((l), (a)); \
58
(a)->start_index = 0; \
72
/* document-related variables */
80
gint max_line_number_margin;
83
gint styles[STYLE_MAX + 1][MAX_TYPES];
85
/* whether we have a wrapped line on page end to take care of on next page */
87
/* set in begin_print() to hold the time when printing was started to ensure all printed
88
* pages have the same date and time (in case of slow machines and many pages where rendering
89
* takes more than a second) */
91
PangoLayout *layout; /* commonly used layout object */
94
/* widget references for the custom widget in the print dialog */
97
GtkWidget *check_print_linenumbers;
98
GtkWidget *check_print_pagenumbers;
99
GtkWidget *check_print_pageheader;
100
GtkWidget *check_print_basename;
101
GtkWidget *entry_print_dateformat;
105
static GtkPrintSettings *settings = NULL;
106
static GtkPageSetup *page_setup = NULL;
110
/* returns the "width" (count of needed characters) for the given number */
111
static gint get_line_numbers_arity(gint x)
114
while ((x /= 10) != 0)
120
/* split a RGB colour into the three colour components */
121
static void get_rgb_values(gint c, gint *r, gint *g, gint *b)
125
*g = (c & - 16711936) / 256;
126
*b = (c & 0xff0000) / 65536;
134
/* creates a commonly used layout object from the given context for use in get_page_count and
136
static PangoLayout *setup_pango_layout(GtkPrintContext *context, PangoFontDescription *desc)
140
layout = gtk_print_context_create_pango_layout(context);
141
pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR);
142
pango_layout_set_spacing(layout, 0);
143
pango_layout_set_attributes(layout, NULL);
144
pango_layout_set_font_description(layout, desc);
150
static gint get_font_width(GtkPrintContext *context, PangoFontDescription *desc)
153
PangoFontMetrics *metrics;
156
pc = gtk_print_context_create_pango_context(context);
158
metrics = pango_context_get_metrics(pc, desc, pango_context_get_language(pc));
159
/** TODO is this the best result we can get? */
160
/* digit and char width are mostly equal for monospace fonts, char width might be
161
* for dual width characters(e.g. Japanese) so use digit width to get sure we get the width
162
* for one character */
163
width = pango_font_metrics_get_approximate_digit_width(metrics) / PANGO_SCALE;
165
pango_font_metrics_unref(metrics);
170
static gint get_page_count(GtkPrintContext *context, DocInfo *dinfo)
172
gdouble width, height;
174
gint i, j, lines_left;
180
width = gtk_print_context_get_width(context);
181
height = gtk_print_context_get_height(context);
183
if (printing_prefs.print_line_numbers)
184
/* remove line number margin space from overall width */
185
width -= dinfo->max_line_number_margin * dinfo->font_width;
187
pango_layout_set_width(dinfo->layout, width * PANGO_SCALE);
189
/* add test text to get line height */
190
pango_layout_set_text(dinfo->layout, "Test 1", -1);
191
pango_layout_get_size(dinfo->layout, NULL, &layout_h);
194
geany_debug("Invalid layout_h (%d). Falling back to default height (%d)",
195
layout_h, 100 * PANGO_SCALE);
196
layout_h = 100 * PANGO_SCALE;
198
dinfo->line_height = (gdouble)layout_h / PANGO_SCALE;
199
dinfo->lines_per_page = ceil((height - dinfo->line_height) / dinfo->line_height);
200
#ifdef GEANY_PRINT_DEBUG
201
geany_debug("max lines_per_page: %d", dinfo->lines_per_page);
203
if (printing_prefs.print_page_numbers)
204
dinfo->lines_per_page -= 2;
205
if (printing_prefs.print_page_header)
206
dinfo->lines_per_page -= 3;
208
lines_left = dinfo->lines_per_page;
211
for (j = 0; j < dinfo->lines; j++)
216
line_buf = sci_get_line(doc_list[dinfo->idx].sci, j);
217
line_width = (g_utf8_strlen(line_buf, -1) + 1) * dinfo->font_width;
218
if (line_width > width)
219
lines = ceil(line_width / width);
220
#ifdef GEANY_PRINT_DEBUG
221
if (lines != 1) geany_debug("%d %d", j+1, lines);
224
while (lines_left < lines)
227
lines_left = dinfo->lines_per_page;
238
static void add_page_header(PangoLayout *layout, cairo_t *cr, DocInfo *dinfo, gint width, gint page_nr)
240
gint ph_height = dinfo->line_height * 3;
243
gchar *tmp_file_name = (doc_list[dinfo->idx].file_name != NULL) ?
244
doc_list[dinfo->idx].file_name : GEANY_STRING_UNTITLED;
245
gchar *file_name = (printing_prefs.page_header_basename) ?
246
g_path_get_basename(tmp_file_name) : g_strdup(tmp_file_name);
249
cairo_set_line_width(cr, 0.3);
250
cairo_set_source_rgb(cr, 0, 0, 0);
251
cairo_rectangle(cr, 2, 2, width - 4, ph_height - 4);
254
/* width - 8: 2px between doc border and frame border, 2px between frame border and text
255
* and this on left and right side, so (2 + 2) * 2 */
256
pango_layout_set_width(layout, (width - 8) * PANGO_SCALE);
258
if ((g_utf8_strlen(file_name, -1) * dinfo->font_width) >= ((width - 4) - (dinfo->font_width * 2)))
259
/* if the filename is wider than the available space on the line, skip parts of it */
260
pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_MIDDLE);
262
data = g_strdup_printf("<b>%s</b>", file_name);
263
pango_layout_set_markup(layout, data, -1);
264
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
265
cairo_move_to(cr, 4, dinfo->line_height * 0.5);
266
pango_cairo_show_layout(cr, layout);
270
data = g_strdup_printf(_("<b>Page %d of %d</b>"), page_nr + 1, dinfo->n_pages);
271
pango_layout_set_markup(layout, data, -1);
272
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
273
cairo_move_to(cr, 4, dinfo->line_height * 1.5);
274
pango_cairo_show_layout(cr, layout);
277
datetime = utils_get_date_time(printing_prefs.page_header_datefmt, &(dinfo->print_time));
278
data = g_strdup_printf("<b>%s</b>", datetime);
279
pango_layout_set_markup(layout, data, -1);
280
pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
281
cairo_move_to(cr, 2, dinfo->line_height * 1.5);
282
pango_cairo_show_layout(cr, layout);
286
/* reset layout and re-position cairo context */
287
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
288
pango_layout_set_ellipsize(layout, FALSE);
289
pango_layout_set_justify(layout, FALSE);
290
pango_layout_set_width(layout, width * PANGO_SCALE);
291
cairo_move_to(cr, 0, dinfo->line_height * 3);
295
static void custom_widget_apply(GtkPrintOperation *operation, GtkWidget *widget, gpointer user_data)
297
PrintWidgets *w = user_data;
299
printing_prefs.print_line_numbers =
300
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->check_print_linenumbers));
302
printing_prefs.print_page_numbers =
303
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->check_print_pagenumbers));
305
printing_prefs.print_page_header =
306
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->check_print_pageheader));
308
printing_prefs.page_header_basename =
309
gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->check_print_basename));
311
g_free(printing_prefs.page_header_datefmt);
312
printing_prefs.page_header_datefmt =
313
g_strdup(gtk_entry_get_text(GTK_ENTRY(w->entry_print_dateformat)));
317
static void on_page_header_toggled(GtkToggleButton *togglebutton, gpointer user_data)
319
gboolean sens = gtk_toggle_button_get_active(togglebutton);
320
PrintWidgets *w = user_data;
322
gtk_widget_set_sensitive(w->check_print_basename, sens);
323
gtk_widget_set_sensitive(w->entry_print_dateformat, sens);
327
static GtkWidget *create_custom_widget(GtkPrintOperation *operation, gpointer user_data)
328
{ /* copied from interface.c */
331
GtkWidget *alignment36;
335
GtkTooltips *tooltips = gtk_tooltips_new();
336
PrintWidgets *w = user_data;
338
gtk_print_operation_set_custom_tab_label(operation, _("Document Setup"));
340
page = gtk_vbox_new(FALSE, 0);
341
gtk_container_set_border_width(GTK_CONTAINER(page), 5);
343
w->check_print_linenumbers = gtk_check_button_new_with_mnemonic(_("Print line numbers"));
344
gtk_box_pack_start(GTK_BOX(page), w->check_print_linenumbers, FALSE, FALSE, 0);
345
gtk_tooltips_set_tip(tooltips, w->check_print_linenumbers, _("Add line numbers to the printed page."), NULL);
346
gtk_button_set_focus_on_click(GTK_BUTTON(w->check_print_linenumbers), FALSE);
347
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->check_print_linenumbers), printing_prefs.print_line_numbers);
349
w->check_print_pagenumbers = gtk_check_button_new_with_mnemonic(_("Print page numbers"));
350
gtk_box_pack_start(GTK_BOX(page), w->check_print_pagenumbers, FALSE, FALSE, 0);
351
gtk_tooltips_set_tip(tooltips, w->check_print_pagenumbers, _("Add page numbers at the bottom of each page. It takes 2 lines of the page."), NULL);
352
gtk_button_set_focus_on_click(GTK_BUTTON(w->check_print_pagenumbers), FALSE);
353
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->check_print_pagenumbers), printing_prefs.print_page_numbers);
355
w->check_print_pageheader = gtk_check_button_new_with_mnemonic(_("Print page header"));
356
gtk_box_pack_start(GTK_BOX(page), w->check_print_pageheader, FALSE, FALSE, 0);
357
gtk_tooltips_set_tip(tooltips, w->check_print_pageheader, _("Adds 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."), NULL);
358
gtk_button_set_focus_on_click(GTK_BUTTON(w->check_print_pageheader), FALSE);
359
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->check_print_pageheader), printing_prefs.print_page_header);
360
g_signal_connect((gpointer) w->check_print_pageheader, "toggled", G_CALLBACK(on_page_header_toggled), w);
362
frame33 = gtk_frame_new(NULL);
363
gtk_box_pack_start(GTK_BOX(page), frame33, FALSE, FALSE, 0);
364
gtk_frame_set_label_align(GTK_FRAME(frame33), 0, 0);
365
gtk_frame_set_shadow_type(GTK_FRAME(frame33), GTK_SHADOW_NONE);
367
alignment36 = gtk_alignment_new(0, 0.5, 1, 1);
368
gtk_container_add(GTK_CONTAINER(frame33), alignment36);
369
gtk_alignment_set_padding(GTK_ALIGNMENT(alignment36), 0, 0, 12, 0);
371
vbox30 = gtk_vbox_new(FALSE, 1);
372
gtk_container_add(GTK_CONTAINER(alignment36), vbox30);
374
w->check_print_basename = gtk_check_button_new_with_mnemonic(_("Use the basename of the printed file"));
375
gtk_box_pack_start(GTK_BOX(vbox30), w->check_print_basename, FALSE, FALSE, 0);
376
gtk_tooltips_set_tip(tooltips, w->check_print_basename, _("Print only the basename(without the path) of the printed file."), NULL);
377
gtk_button_set_focus_on_click(GTK_BUTTON(w->check_print_basename), FALSE);
378
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->check_print_basename), printing_prefs.page_header_basename);
380
hbox10 = gtk_hbox_new(FALSE, 5);
381
gtk_box_pack_start(GTK_BOX(vbox30), hbox10, TRUE, TRUE, 0);
383
label203 = gtk_label_new(_("Date format:"));
384
gtk_box_pack_start(GTK_BOX(hbox10), label203, FALSE, FALSE, 0);
386
w->entry_print_dateformat = gtk_entry_new();
387
gtk_box_pack_start(GTK_BOX(hbox10), w->entry_print_dateformat, TRUE, TRUE, 0);
388
gtk_tooltips_set_tip(tooltips, 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."), NULL);
389
gtk_entry_set_text(GTK_ENTRY(w->entry_print_dateformat), printing_prefs.page_header_datefmt);
391
on_page_header_toggled(GTK_TOGGLE_BUTTON(w->check_print_pageheader), w);
392
gtk_widget_show_all(page);
397
static void end_print(GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data)
399
DocInfo *dinfo = user_data;
404
g_object_unref(dinfo->layout);
408
static void begin_print(GtkPrintOperation *operation, GtkPrintContext *context, gpointer user_data)
410
DocInfo *dinfo = user_data;
411
PangoFontDescription *desc;
418
desc = pango_font_description_from_string(prefs.editor_font);
420
/* init dinfo fields */
421
dinfo->lines = sci_get_line_count(doc_list[dinfo->idx].sci);
422
dinfo->lines_per_page = 0;
425
dinfo->long_line = FALSE;
426
dinfo->print_time = time(NULL);
427
dinfo->max_line_number_margin = get_line_numbers_arity(dinfo->lines) + 1;
428
/* increase font width by 1 (looks better) */
429
dinfo->font_width = get_font_width(context, desc) + 1;
430
/* create a PangoLayout to be commonly used in get_page_count and draw_page */
431
dinfo->layout = setup_pango_layout(context, desc);
432
/* this is necessary because of possible line breaks on the printed page and then
433
* lines_per_page differs from document line count */
434
dinfo->n_pages = get_page_count(context, dinfo);
436
/* read all styles from Scintilla */
437
style_max = pow(2, scintilla_send_message(doc_list[dinfo->idx].sci, SCI_GETSTYLEBITS, 0, 0));
438
/* if the lexer uses only the first 32 styles(style bits = 5),
439
* we need to add the pre-defined styles */
441
style_max = STYLE_LASTPREDEFINED;
442
for (i = 0; i < style_max; i++)
444
dinfo->styles[i][FORE] = ROTATE_RGB(scintilla_send_message(
445
doc_list[dinfo->idx].sci, SCI_STYLEGETFORE, i, 0));
446
if (i == STYLE_LINENUMBER)
447
{ /* ignore background colour for line number margin to avoid trouble with wrapped lines */
448
dinfo->styles[STYLE_LINENUMBER][BACK] = ROTATE_RGB(scintilla_send_message(
449
doc_list[dinfo->idx].sci, SCI_STYLEGETBACK, STYLE_DEFAULT, 0));
453
dinfo->styles[i][BACK] = ROTATE_RGB(scintilla_send_message(
454
doc_list[dinfo->idx].sci, SCI_STYLEGETBACK, i, 0));
456
dinfo->styles[i][BOLD] =
457
scintilla_send_message(doc_list[dinfo->idx].sci, SCI_STYLEGETBOLD, i, 0);
458
dinfo->styles[i][ITALIC] =
459
scintilla_send_message(doc_list[dinfo->idx].sci, SCI_STYLEGETITALIC, i, 0);
462
if (dinfo->n_pages >= 0)
463
gtk_print_operation_set_n_pages(operation, dinfo->n_pages);
465
pango_font_description_free(desc);
469
static void draw_page(GtkPrintOperation *operation, GtkPrintContext *context,
470
gint page_nr, gpointer user_data)
472
DocInfo *dinfo = user_data;
474
gdouble width, height;
480
if (dinfo == NULL || page_nr >= dinfo->n_pages)
483
#ifdef GEANY_PRINT_DEBUG
484
geany_debug("draw_page = %d, pages = %d, (real) lines_per_page = %d",
485
page_nr, dinfo->n_pages, dinfo->lines_per_page);
488
str = g_string_sized_new(256);
489
cr = gtk_print_context_get_cairo_context(context);
490
width = gtk_print_context_get_width(context);
491
height = gtk_print_context_get_height(context);
493
cairo_set_source_rgb(cr, 0, 0, 0);
494
#ifdef GEANY_PRINT_DEBUG
495
cairo_set_line_width(cr, 0.2);
496
cairo_rectangle(cr, 0, 0, width, height);
499
cairo_move_to(cr, 0, 0);
501
pango_layout_set_width(dinfo->layout, width * PANGO_SCALE);
503
if (printing_prefs.print_page_header)
504
add_page_header(dinfo->layout, cr, dinfo, width, page_nr);
506
count = 0; /* the actual line counter for the current page, might be different from
507
* dinfo->cur_line due to possible line breaks */
508
while (count < dinfo->lines_per_page)
512
PangoAttrList *layout_attr;
513
PangoAttribute *attr;
514
gint colours[3] = { 0 };
515
gboolean add_linenumber = TRUE;
518
while (count < dinfo->lines_per_page && c != '\0')
522
g_string_erase(str, 0, str->len); /* clear the string */
525
if (printing_prefs.print_line_numbers && add_linenumber)
527
/* if we had a wrapped line on the last page which needs to be continued, don't
528
* add a line number */
529
if (dinfo->long_line)
531
add_linenumber = FALSE;
535
gchar *line_number = NULL;
536
gint cur_line_number_margin = get_line_numbers_arity(dinfo->cur_line + 1);
537
gchar *fill = g_strnfill(
538
dinfo->max_line_number_margin - cur_line_number_margin - 1, ' ');
540
line_number = g_strdup_printf("%s%d ", fill, dinfo->cur_line + 1);
541
g_string_append(str, line_number);
542
dinfo->cur_line++; /* increase document line */
543
add_linenumber = FALSE;
544
style = STYLE_LINENUMBER;
545
c = 'a'; /* dummy value */
553
style = sci_get_style_at(doc_list[dinfo->idx].sci, dinfo->cur_pos);
554
c = sci_get_char_at(doc_list[dinfo->idx].sci, dinfo->cur_pos);
555
if (c == '\0' || style == -1)
556
{ /* if c gets 0, we are probably out of document boundaries,
557
* so stop to break out of outer loop */
558
count = dinfo->lines_per_page;
564
/* convert tabs to spaces which seems to be better than using Pango tabs */
567
gchar *s = g_strnfill(editor_prefs.tab_width, ' ');
568
g_string_append(str, s);
571
/* don't add line breaks, they are handled manually below */
572
else if (c == '\r' || c == '\n')
574
gchar c_next = sci_get_char_at(doc_list[dinfo->idx].sci, dinfo->cur_pos);
576
if (c == '\r' && c_next == '\n')
577
dinfo->cur_pos++; /* skip LF part of CR/LF */
581
g_string_append_c(str, c); /* finally add the character */
583
/* handle UTF-8: since we add char by char (better: byte by byte), we need to
584
* keep UTF-8 characters together(e.g. two bytes for one character)
585
* the input is always UTF-8 and c is signed, so all non-Ascii
586
* characters are less than 0 and consist of all bytes less than 0.
587
* style doesn't change since it is only one character with multiple bytes. */
590
c = sci_get_char_at(doc_list[dinfo->idx].sci, dinfo->cur_pos);
592
{ /* only add the byte when it is part of the UTF-8 character
593
* otherwise we could add e.g. a '\n' and it won't be visible in the
594
* printed document */
595
g_string_append_c(str, c);
605
pango_layout_set_text(dinfo->layout, str->str, -1);
607
layout_attr = pango_attr_list_new();
608
/* foreground colour */
609
get_rgb_values(dinfo->styles[style][FORE], &colours[0], &colours[1], &colours[2]);
610
attr = pango_attr_foreground_new(colours[0], colours[1], colours[2]);
611
ADD_ATTR(layout_attr, attr);
612
/* background colour */
613
get_rgb_values(dinfo->styles[style][BACK], &colours[0], &colours[1], &colours[2]);
614
attr = pango_attr_background_new(colours[0], colours[1], colours[2]);
615
ADD_ATTR(layout_attr, attr);
617
if (dinfo->styles[style][BOLD])
619
attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
620
ADD_ATTR(layout_attr, attr);
623
if (dinfo->styles[style][ITALIC])
625
attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
626
ADD_ATTR(layout_attr, attr);
628
pango_layout_set_attributes(dinfo->layout, layout_attr);
629
pango_layout_context_changed(dinfo->layout);
630
pango_attr_list_unref(layout_attr);
633
cairo_get_current_point(cr, &x, &y);
636
/* normal line break at eol character in document */
639
/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
640
/*cairo_move_to(cr, 0, y + (gdouble)layout_h / PANGO_SCALE);*/
641
cairo_move_to(cr, 0, y + dinfo->line_height);
644
/* we added a new document line so request a new line number */
645
add_linenumber = TRUE;
650
/* maybe we need to force a line break because of too long line */
651
if (x >= (width - dinfo->font_width))
653
/* don't start the line at horizontal origin because we need to skip the
654
* line number margin */
655
if (printing_prefs.print_line_numbers)
657
x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
660
/*pango_layout_get_size(dinfo->layout, NULL, &layout_h);*/
661
/*cairo_move_to(cr, x_offset, y + (gdouble)layout_h / PANGO_SCALE);*/
662
/* this is faster but not exactly the same as above */
663
cairo_move_to(cr, x_offset, y + dinfo->line_height);
664
cairo_get_current_point(cr, &x, &y);
667
if (count < dinfo->lines_per_page)
669
/* str->len is counted in bytes not characters, so use g_utf8_strlen() */
670
x_offset = (g_utf8_strlen(str->str, -1) * dinfo->font_width);
672
if (dinfo->long_line && count == 0)
674
x_offset = (dinfo->max_line_number_margin + 1) * dinfo->font_width;
675
dinfo->long_line = FALSE;
678
pango_cairo_show_layout(cr, dinfo->layout);
679
cairo_move_to(cr, x + x_offset, y);
682
/* we are on a wrapped line but we are out of lines on this page, so continue
683
* the current line on the next page and remember to continue in current line */
684
dinfo->long_line = TRUE;
689
if (printing_prefs.print_line_numbers)
690
{ /* print a thin line between the line number margin and the data */
693
if (printing_prefs.print_page_header)
694
y_start = (dinfo->line_height * 3) - 2; /* "- 2": to connect the line number line to
695
* the page header frame */
697
cairo_set_line_width(cr, 0.3);
698
cairo_move_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1, y_start);
699
cairo_line_to(cr, (dinfo->max_line_number_margin * dinfo->font_width) + 1,
700
y + dinfo->line_height); /* y is last added line, we reuse it */
704
if (printing_prefs.print_page_numbers)
706
gchar *line = g_strdup_printf("<small>- %d -</small>", page_nr + 1);
707
pango_layout_set_markup(dinfo->layout, line, -1);
708
pango_layout_set_alignment(dinfo->layout, PANGO_ALIGN_CENTER);
709
cairo_move_to(cr, 0, height - dinfo->line_height);
710
pango_cairo_show_layout(cr, dinfo->layout);
713
#ifdef GEANY_PRINT_DEBUG
714
cairo_set_line_width(cr, 0.3);
715
cairo_move_to(cr, 0, height - (1.25 * dinfo->line_height));
716
cairo_line_to(cr, width - 1, height - (1.25 * dinfo->line_height));
720
g_string_free(str, TRUE);
724
static void status_changed(GtkPrintOperation *op, gpointer data)
726
gchar *filename = (data != NULL) ? data : GEANY_STRING_UNTITLED;
727
if (gtk_print_operation_get_status(op) == GTK_PRINT_STATUS_FINISHED_ABORTED)
728
msgwin_status_add(_("Printing of file %s was cancelled."), filename);
729
else if (gtk_print_operation_get_status(op) == GTK_PRINT_STATUS_FINISHED)
730
msgwin_status_add(_("File %s printed."), filename);
734
static void printing_print_gtk(gint idx)
736
GtkPrintOperation *op;
737
GtkPrintOperationResult res = GTK_PRINT_OPERATION_RESULT_ERROR;
738
GError *error = NULL;
740
PrintWidgets *widgets;
742
/** TODO check for monospace font, detect the widest character in the font and
743
* use it at font_width */
745
widgets = g_new0(PrintWidgets, 1);
746
dinfo = g_new0(DocInfo, 1);
747
/* all other fields are initialised in begin_print() */
750
op = gtk_print_operation_new();
752
gtk_print_operation_set_unit(op, GTK_UNIT_POINTS);
753
gtk_print_operation_set_show_progress(op, TRUE);
755
g_signal_connect(op, "begin-print", G_CALLBACK(begin_print), dinfo);
756
g_signal_connect(op, "end-print", G_CALLBACK(end_print), dinfo);
757
g_signal_connect(op, "draw-page", G_CALLBACK(draw_page), dinfo);
758
g_signal_connect(op, "status-changed", G_CALLBACK(status_changed), doc_list[idx].file_name);
759
g_signal_connect(op, "create-custom-widget", G_CALLBACK(create_custom_widget), widgets);
760
g_signal_connect(op, "custom-widget-apply", G_CALLBACK(custom_widget_apply), widgets);
762
if (settings != NULL)
763
gtk_print_operation_set_print_settings(op, settings);
764
if (page_setup != NULL)
765
gtk_print_operation_set_default_page_setup(op, page_setup);
767
res = gtk_print_operation_run(
768
op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG, GTK_WINDOW(app->window), &error);
770
if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
772
if (settings != NULL)
773
g_object_unref(settings);
774
settings = g_object_ref(gtk_print_operation_get_print_settings(op));
775
/* status message is printed in the status-changed handler */
777
else if (res == GTK_PRINT_OPERATION_RESULT_ERROR)
779
dialogs_show_msgbox(GTK_MESSAGE_ERROR, _("Printing of %s failed (%s)."),
780
doc_list[idx].file_name, error->message);
790
void printing_page_setup_gtk(void)
792
GtkPageSetup *new_page_setup;
794
if (settings == NULL)
795
settings = gtk_print_settings_new();
797
new_page_setup = gtk_print_run_page_setup_dialog(
798
GTK_WINDOW(app->window), page_setup, settings);
800
if (page_setup != NULL)
801
g_object_unref(page_setup);
803
page_setup = new_page_setup;
805
#endif /* GTK 2.10 */
808
/* simple file print using an external tool */
809
static void print_external(gint idx)
813
if (doc_list[idx].file_name == NULL)
816
if (! NZV(printing_prefs.external_print_cmd))
818
dialogs_show_msgbox(GTK_MESSAGE_ERROR,
819
_("Please set a print command in the preferences dialog first"));
823
cmdline = g_strdup(printing_prefs.external_print_cmd);
824
cmdline = utils_str_replace(cmdline, "%f", doc_list[idx].file_name);
826
if (dialogs_show_question(
827
_("The file \"%s\" will be printed with the following command:\n\n%s"),
828
doc_list[idx].file_name, cmdline))
830
GError *error = NULL;
833
gchar *tmp_cmdline = g_strdup(cmdline);
835
/* /bin/sh -c emulates the system() call and makes complex commands possible
836
* but only needed on non-win32 systems due to the lack of win32's shell capabilities */
837
gchar *tmp_cmdline = g_strconcat("/bin/sh -c \"", cmdline, "\"", NULL);
840
if (! g_spawn_command_line_async(tmp_cmdline, &error))
842
dialogs_show_msgbox(GTK_MESSAGE_ERROR,
843
_("Printing of \"%s\" failed (return code: %s)."),
844
doc_list[idx].file_name, error->message);
849
msgwin_status_add(_("File %s printed."), doc_list[idx].file_name);
857
void printing_print_doc(gint idx)
859
if (! DOC_IDX_VALID(idx))
862
#if GTK_CHECK_VERSION(2, 10, 0)
863
if (gtk_check_version(2, 10, 0) == NULL && printing_prefs.use_gtk_printing)
864
printing_print_gtk(idx);