220 lines
6.8 KiB
C
220 lines
6.8 KiB
C
/*
|
|
* L3afpad - GTK+ based simple text editor
|
|
* Copyright (C) 2004-2007 Tarot Osuji
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include <gtk/gtk.h>
|
|
#include "gtkprint.h"
|
|
|
|
static PangoLayout *layout;
|
|
static const PangoFontDescription *font_desc;
|
|
static gint line_count, lines_per_page, text_height;
|
|
static gint n_pages;
|
|
static gdouble page_width, page_height;
|
|
static const gchar *page_title = NULL;
|
|
|
|
static void get_tab_array(PangoTabArray **tabs,
|
|
GtkPrintContext *ctx, GtkTextView *text_view)
|
|
{
|
|
gint xft_dpi, loc;
|
|
GtkSettings *settings = gtk_settings_get_default();
|
|
|
|
g_object_get(settings, "gtk-xft-dpi", &xft_dpi, NULL);
|
|
if ((*tabs = gtk_text_view_get_tabs(text_view))) {
|
|
pango_tab_array_get_tab(*tabs, 0, NULL, &loc);
|
|
pango_tab_array_set_tab(*tabs, 0, PANGO_TAB_LEFT,
|
|
loc * gtk_print_context_get_dpi_x(ctx) / (xft_dpi / PANGO_SCALE));
|
|
}
|
|
}
|
|
|
|
static void cb_begin_print(GtkPrintOperation *op,
|
|
GtkPrintContext *ctx, gpointer data)
|
|
{
|
|
gint layout_height;
|
|
gchar *text;
|
|
GtkTextIter start, end;
|
|
GtkTextBuffer *buffer = gtk_text_view_get_buffer(data);
|
|
PangoTabArray *tabs;
|
|
|
|
gtk_text_buffer_get_bounds(buffer, &start, &end);
|
|
text = g_strchomp(gtk_text_buffer_get_text(buffer, &start, &end, FALSE));
|
|
|
|
page_width = gtk_print_context_get_width(ctx);
|
|
page_height = gtk_print_context_get_height(ctx);
|
|
font_desc = gtk_style_context_get_font(gtk_widget_get_style_context(data), GTK_STATE_FLAG_NORMAL);
|
|
layout = gtk_print_context_create_pango_layout(ctx);
|
|
pango_layout_set_width(layout, page_width * PANGO_SCALE);
|
|
pango_layout_set_font_description(layout, font_desc);
|
|
pango_layout_set_text(layout, text, -1);
|
|
|
|
get_tab_array(&tabs, ctx, data);
|
|
if (tabs) {
|
|
pango_layout_set_tabs(layout, tabs);
|
|
pango_tab_array_free(tabs);
|
|
}
|
|
pango_layout_get_size(layout, NULL, &layout_height);
|
|
|
|
line_count = pango_layout_get_line_count(layout);
|
|
text_height = pango_font_description_get_size(font_desc) / PANGO_SCALE;
|
|
lines_per_page = page_height / text_height;
|
|
|
|
n_pages = (line_count - 1) / lines_per_page + 1;
|
|
gtk_print_operation_set_n_pages(op, n_pages);
|
|
|
|
g_free(text);
|
|
}
|
|
|
|
static void cb_draw_page(GtkPrintOperation *op,
|
|
GtkPrintContext *ctx, gint page_nr, gpointer data)
|
|
{
|
|
cairo_t *cr;
|
|
PangoLayoutLine *line;
|
|
gint n_line, i, j = 0;
|
|
|
|
PangoLayout *layout_lh, *layout_rh;
|
|
gchar *page_text;
|
|
gint layout_width;
|
|
|
|
cr = gtk_print_context_get_cairo_context(ctx);
|
|
|
|
layout_lh = gtk_print_context_create_pango_layout(ctx);
|
|
pango_layout_set_font_description(layout_lh, font_desc);
|
|
pango_layout_set_text(layout_lh, page_title, -1);
|
|
cairo_move_to(cr, 0, - 72 / 25.4 * 10);
|
|
pango_cairo_show_layout(cr, layout_lh);
|
|
|
|
page_text = g_strdup_printf("%d / %d", page_nr + 1, n_pages);
|
|
layout_rh = gtk_print_context_create_pango_layout(ctx);
|
|
pango_layout_set_font_description(layout_rh, font_desc);
|
|
pango_layout_set_text(layout_rh, page_text, -1);
|
|
// pango_layout_set_alignment(layout_rh, PANGO_ALIGN_RIGHT);
|
|
pango_layout_get_size(layout_rh, &layout_width, NULL);
|
|
cairo_move_to(cr,
|
|
page_width - layout_width / PANGO_SCALE, - 72 / 25.4 * 10);
|
|
pango_cairo_show_layout(cr, layout_rh);
|
|
g_free(page_text);
|
|
|
|
if (line_count > lines_per_page * (page_nr + 1))
|
|
n_line = lines_per_page * (page_nr + 1);
|
|
else
|
|
n_line = line_count;
|
|
|
|
for (i = lines_per_page * page_nr; i < n_line; i++) {
|
|
line = pango_layout_get_line(layout, i);
|
|
cairo_move_to(cr, 0, text_height * (j + 1));
|
|
pango_cairo_show_layout_line(cr, line);
|
|
j++;
|
|
}
|
|
}
|
|
|
|
static void cb_end_print(GtkPrintOperation *op,
|
|
GtkPrintContext *ctx, gpointer data)
|
|
{
|
|
g_object_unref(layout);
|
|
}
|
|
|
|
static GtkPrintSettings *settings = NULL;
|
|
|
|
static GtkPrintOperation *create_print_operation(GtkTextView *text_view)
|
|
{
|
|
GtkPrintOperation *op;
|
|
static GtkPageSetup *page_setup = NULL;
|
|
|
|
op = gtk_print_operation_new();
|
|
|
|
if (settings)
|
|
gtk_print_operation_set_print_settings(op, settings);
|
|
|
|
if (!page_setup) {
|
|
page_setup = gtk_page_setup_new();
|
|
gtk_page_setup_set_top_margin(page_setup, 25.0, GTK_UNIT_MM);
|
|
gtk_page_setup_set_bottom_margin(page_setup, 20.0, GTK_UNIT_MM);
|
|
gtk_page_setup_set_left_margin(page_setup, 20.0, GTK_UNIT_MM);
|
|
gtk_page_setup_set_right_margin(page_setup, 20.0, GTK_UNIT_MM);
|
|
}
|
|
gtk_print_operation_set_default_page_setup(op, page_setup);
|
|
|
|
g_signal_connect(op, "begin-print", G_CALLBACK(cb_begin_print), text_view);
|
|
g_signal_connect(op, "draw-page", G_CALLBACK(cb_draw_page), NULL);
|
|
g_signal_connect(op, "end-print", G_CALLBACK(cb_end_print), NULL);
|
|
|
|
return op;
|
|
}
|
|
|
|
static void create_error_dialog(GtkTextView *text_view, gchar *message)
|
|
{
|
|
GtkWidget *dialog;
|
|
|
|
dialog = gtk_message_dialog_new(
|
|
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(text_view))),
|
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
GTK_MESSAGE_ERROR,
|
|
GTK_BUTTONS_NONE,
|
|
"%s", message);
|
|
gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE);
|
|
gtk_dialog_add_buttons(GTK_DIALOG(dialog),
|
|
GTK_STOCK_OK, GTK_RESPONSE_CANCEL, NULL);
|
|
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CANCEL);
|
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
|
gtk_widget_destroy(dialog);
|
|
}
|
|
|
|
void create_gtkprint_session(GtkTextView *text_view, const gchar *title)
|
|
{
|
|
GtkPrintOperation *op;
|
|
GtkPrintOperationResult res;
|
|
GError *err = NULL;
|
|
|
|
page_title = title;
|
|
op = create_print_operation(text_view);
|
|
|
|
res = gtk_print_operation_run(op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
|
|
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(text_view))), &err);
|
|
switch (res) {
|
|
case GTK_PRINT_OPERATION_RESULT_ERROR:
|
|
create_error_dialog(text_view, err->message);
|
|
g_error_free(err);
|
|
case GTK_PRINT_OPERATION_RESULT_APPLY:
|
|
if (settings)
|
|
g_object_unref(settings);
|
|
settings = g_object_ref(gtk_print_operation_get_print_settings(op));
|
|
default:
|
|
break;
|
|
}
|
|
|
|
g_object_unref(op);
|
|
}
|
|
|
|
void create_gtkprint_preview_session(GtkTextView *text_view, const gchar *title)
|
|
{
|
|
GtkPrintOperation *op;
|
|
GtkPrintOperationResult res;
|
|
GError *err = NULL;
|
|
|
|
page_title = title;
|
|
op = create_print_operation(text_view);
|
|
|
|
res = gtk_print_operation_run(op, GTK_PRINT_OPERATION_ACTION_PREVIEW,
|
|
GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(text_view))), &err);
|
|
if (res == GTK_PRINT_OPERATION_RESULT_ERROR) {
|
|
create_error_dialog(text_view, err->message);
|
|
g_error_free(err);
|
|
}
|
|
|
|
g_object_unref(op);
|
|
}
|