/* * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a * aplicativos mainframe. Registro no INPI sob o nome G3270. * * Copyright (C) <2008> * * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela * Free Software Foundation. * * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para * obter mais detalhes. * * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA, 02111-1307, USA * * Este programa está nomeado como print.c e possui - linhas de código. * * Contatos: * * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) * licinio@bb.com.br (Licínio Luis Branco) * kraucer@bb.com.br (Kraucer Fernandes Mazuco) * */ #include "globals.h" #include "v3270/v3270.h" #include /*--[ Structs ]--------------------------------------------------------------------------------------*/ typedef struct _print_info { GdkColor color[V3270_COLOR_COUNT]; int show_selection : 1; int all : 1; H3270 * session; gchar * font; guint fontsize; cairo_font_weight_t fontweight; int baddr; int rows; int cols; int pages; cairo_font_extents_t extents; double left; double width; double height; cairo_scaled_font_t * font_scaled; } PRINT_INFO; /*--[ Implement ]------------------------------------------------------------------------------------*/ static void setup_font(GtkPrintContext * context, PRINT_INFO *info) { cairo_t *cr = gtk_print_context_get_cairo_context(context); cairo_select_font_face(cr, info->font, CAIRO_FONT_SLANT_NORMAL, info->fontweight); info->font_scaled = cairo_get_scaled_font(cr); cairo_scaled_font_reference(info->font_scaled); cairo_scaled_font_extents(info->font_scaled,&info->extents); info->width = ((double) info->cols) * info->extents.max_x_advance; info->height = ((double) info->rows) * (info->extents.height + info->extents.descent); // Center image info->left = (gtk_print_context_get_width(context)-info->width)/2; if(info->left < 2) info->left = 2; } static void begin_print(GtkPrintOperation *prt, GtkPrintContext *context, PRINT_INFO *info) { setup_font(context,info); gtk_print_operation_set_n_pages(prt,1); } static void draw_page(GtkPrintOperation *prt, GtkPrintContext *context, gint pg, PRINT_INFO *info) { int row; int col; cairo_t * cr = gtk_print_context_get_cairo_context(context); int baddr = info->baddr; GdkRectangle rect; cairo_set_scaled_font(cr,info->font_scaled); memset(&rect,0,sizeof(rect)); rect.y = 2; rect.height = (info->extents.height + info->extents.descent); rect.width = info->extents.max_x_advance; gdk_cairo_set_source_color(cr,info->color+V3270_COLOR_BACKGROUND); cairo_rectangle(cr, info->left-2, 0, (rect.width*info->cols)+4, (rect.height*info->rows)+4); cairo_fill(cr); cairo_stroke(cr); rect.width++; rect.height++; for(row = 0; row < info->rows; row++) { rect.x = info->left; for(col = 0; col < info->cols; col++) { unsigned char c; unsigned short attr; if(!lib3270_get_element(info->session,baddr++,&c,&attr) && (info->all || (attr & LIB3270_ATTR_SELECTED))) { if(!info->show_selection) attr &= ~LIB3270_ATTR_SELECTED; v3270_draw_element(cr,c,attr,info->session,info->extents.height,&rect,info->color); } rect.x += (rect.width-1); } rect.y += (rect.height-1); } } #ifdef WIN32 #define save_string(h,k,v) save_settings(k,v,h) #define save_double(h,k,v) registry_set_double(h,k,v) static void save_settings(const gchar *key, const gchar *value, HKEY hKey) { RegSetValueEx(hKey,key,0,REG_SZ,(const BYTE *) value,strlen(value)+1); } /* * From: http://git.gnome.org/browse/gtk+/tree/gtk/gtkpagesetup.c * something like this should really be in gobject! * * I Agree!! (Perry Werneck) * */ static gchar * enum_to_string(GType type, guint enum_value) { GEnumClass *enum_class; GEnumValue *value; gchar *retval = NULL; enum_class = g_type_class_ref (type); value = g_enum_get_value(enum_class, enum_value); if (value) retval = g_strdup (value->value_nick); g_type_class_unref (enum_class); return retval; } #endif // WIN32 static void done(GtkPrintOperation *prt, GtkPrintOperationResult result, PRINT_INFO *info) { #ifdef WIN32 HKEY registry; if(get_registry_handle("print",®istry,KEY_SET_VALUE)) { HKEY hKey; DWORD disp; if(RegCreateKeyEx(registry,"settings",0,NULL,REG_OPTION_NON_VOLATILE,KEY_SET_VALUE,NULL,&hKey,&disp) == ERROR_SUCCESS) { gtk_print_settings_foreach( gtk_print_operation_get_print_settings(prt), (GtkPrintSettingsFunc) save_settings, hKey ); RegCloseKey(hKey); } if(RegCreateKeyEx(registry,"pagesetup",0,NULL,REG_OPTION_NON_VOLATILE,KEY_SET_VALUE,NULL,&hKey,&disp) == ERROR_SUCCESS) { HKEY hPaperSize; GtkPageSetup * setup = gtk_print_operation_get_default_page_setup(prt); gchar * orientation = enum_to_string(GTK_TYPE_PAGE_ORIENTATION,gtk_page_setup_get_orientation(setup)); // From http://git.gnome.org/browse/gtk+/tree/gtk/gtkpagesetup.c save_double(hKey, "MarginTop", gtk_page_setup_get_top_margin(setup, GTK_UNIT_MM)); save_double(hKey, "MarginBottom", gtk_page_setup_get_bottom_margin(setup, GTK_UNIT_MM)); save_double(hKey, "MarginLeft", gtk_page_setup_get_left_margin(setup, GTK_UNIT_MM)); save_double(hKey, "MarginRight", gtk_page_setup_get_right_margin(setup, GTK_UNIT_MM)); save_string(hKey, "Orientation", orientation); g_free (orientation); if(RegCreateKeyEx(hKey,"papersize",0,NULL,REG_OPTION_NON_VOLATILE,KEY_SET_VALUE,NULL,&hPaperSize,&disp) == ERROR_SUCCESS) { GtkPaperSize *size = gtk_page_setup_get_paper_size(setup); if(size) { // From http://git.gnome.org/browse/gtk+/tree/gtk/gtkpapersize.c const gchar *name = gtk_paper_size_get_name(size); const gchar *display_name = gtk_paper_size_get_display_name(size); const gchar *ppd_name = gtk_paper_size_get_ppd_name(size); if (ppd_name != NULL) save_string(hPaperSize,"PPDName", ppd_name); else save_string(hPaperSize,"Name", name); if (display_name) save_string(hPaperSize,"DisplayName", display_name); save_double(hPaperSize, "Width", gtk_paper_size_get_width (size, GTK_UNIT_MM)); save_double(hPaperSize, "Height", gtk_paper_size_get_height (size, GTK_UNIT_MM)); } RegCloseKey(hPaperSize); } RegCloseKey(hKey); } RegCloseKey(registry); } #else GKeyFile * conf = get_application_keyfile(); gtk_print_settings_to_key_file(gtk_print_operation_get_print_settings(prt),conf,"print_settings"); gtk_page_setup_to_key_file(gtk_print_operation_get_default_page_setup(prt),conf,"page_setup"); #endif if(info->font_scaled) cairo_scaled_font_destroy(info->font_scaled); if(info->font) g_free(info->font); g_free(info); } #if GTK_CHECK_VERSION(3,2,0) static gboolean filter_monospaced(const PangoFontFamily *family,const PangoFontFace *face,gpointer data) { return pango_font_family_is_monospace((PangoFontFamily *) family); } #endif // GTK(3,2,0) static void font_set(GtkFontButton *widget, PRINT_INFO *info) { const gchar * name = gtk_font_button_get_font_name(widget); PangoFontDescription * descr = pango_font_description_from_string(name); if(!descr) return; if(info->font) g_free(info->font); info->font = g_strdup(pango_font_description_get_family(descr)); info->fontsize = pango_font_description_get_size(descr); info->fontweight = CAIRO_FONT_WEIGHT_NORMAL; if(pango_font_description_get_weight(descr) == PANGO_WEIGHT_BOLD) info->fontweight = CAIRO_FONT_WEIGHT_BOLD; pango_font_description_free(descr); set_string_to_config("print","font",name); trace("Font set to \"%s\" with size %d",info->font,info->fontsize); } static void toggle_show_selection(GtkToggleButton *togglebutton,PRINT_INFO *info) { gboolean active = gtk_toggle_button_get_active(togglebutton); info->show_selection = active ? 1 : 0; set_boolean_to_config("print","selection",active); } static GObject * create_custom_widget(GtkPrintOperation *prt, PRINT_INFO *info) { static const gchar * text[] = { N_( "_Font:" ), N_( "C_olor scheme:" ) }; GtkWidget * container = gtk_table_new(3,2,FALSE); GtkWidget * label[G_N_ELEMENTS(text)]; GtkWidget * widget; int f; gchar * ptr; for(f=0;ffont = get_string_from_config("print","font","Courier 10"); gtk_font_button_set_font_name((GtkFontButton *) widget,info->font); font_set((GtkFontButton *) widget,info); g_signal_connect(G_OBJECT(widget),"font-set",G_CALLBACK(font_set),info); // Color scheme dropdown ptr = get_string_from_config("print","colors",""); if(*ptr) v3270_set_color_table(info->color,ptr); else v3270_set_mono_color_table(info->color,"black","white"); g_free(ptr); widget = color_scheme_new(info->color); gtk_label_set_mnemonic_widget(GTK_LABEL(label[1]),widget); g_object_set_data(G_OBJECT(container),"combo",widget); gtk_table_attach(GTK_TABLE(container),widget,1,2,1,2,GTK_EXPAND|GTK_FILL,GTK_FILL,5,0); // Selection checkbox widget = gtk_check_button_new_with_label(_("Print selection box")); if(info->all) { info->show_selection = get_boolean_from_config("print","selection",FALSE); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget),info->show_selection); g_signal_connect(G_OBJECT(widget),"toggled",G_CALLBACK(toggle_show_selection),info); } else { gtk_widget_set_sensitive(widget,FALSE); } gtk_table_attach(GTK_TABLE(container),widget,1,2,2,3,GTK_EXPAND|GTK_FILL,GTK_FILL,5,0); // Show and return gtk_widget_show_all(container); return G_OBJECT(container); } static void custom_widget_apply(GtkPrintOperation *prt, GtkWidget *widget, PRINT_INFO *info) { GtkWidget * combo = g_object_get_data(G_OBJECT(widget),"combo"); GdkColor * clr = g_object_get_data(G_OBJECT(combo),"selected"); if(clr) { int f; GString *str = g_string_new(""); for(f=0;fcolor[f] = clr[f]; if(f) g_string_append_c(str,','); g_string_append_printf(str,"%s",gdk_color_to_string(clr+f)); } set_string_to_config("print","colors","%s",str->str); g_string_free(str,TRUE); } g_object_unref(combo); } #ifdef WIN32 void update_settings(const gchar *key, const gchar *val, gpointer *settings) { gtk_print_settings_set(GTK_PRINT_SETTINGS(settings), key, val); } #endif // WIN32 static GtkPrintOperation * begin_print_operation(GtkAction *action, GtkWidget *widget, PRINT_INFO **info) { GtkPrintOperation * print = gtk_print_operation_new(); GtkPrintSettings * settings = gtk_print_settings_new(); GtkPageSetup * setup = gtk_page_setup_new(); const gchar * attr; *info = g_new0(PRINT_INFO,1); (*info)->session = v3270_get_session(widget); (*info)->fontweight = CAIRO_FONT_WEIGHT_NORMAL; // Basic setup gtk_print_operation_set_allow_async(print,TRUE); attr = (const gchar *) g_object_get_data(G_OBJECT(action),"jobname"); if(attr) { gtk_print_operation_set_job_name(print,attr); } else { gchar *ptr = g_strconcat(PACKAGE_NAME,".",gtk_action_get_name(action),NULL); gtk_print_operation_set_job_name(print,ptr); g_free(ptr); } gtk_print_operation_set_custom_tab_label(print,_( "Options" )); gtk_print_operation_set_show_progress(print,TRUE); // Common signals g_signal_connect(print,"done",G_CALLBACK(done),*info); g_signal_connect(print,"create-custom-widget",G_CALLBACK(create_custom_widget), *info); g_signal_connect(print,"custom-widget-apply",G_CALLBACK(custom_widget_apply), *info); // Load page and print settings { #ifdef WIN32 HKEY registry; if(get_registry_handle("print",®istry,KEY_READ)) { HKEY hKey; DWORD disp; registry_foreach(registry,"settings",update_settings,(gpointer) settings); if(RegCreateKeyEx(registry,"pagesetup",0,NULL,REG_OPTION_NON_VOLATILE,KEY_READ,NULL,&hKey,&disp) == ERROR_SUCCESS) { gdouble val; #define load_double(h,k,s) if(registry_get_double(h,k,&val)) s(setup, val,GTK_UNIT_MM); load_double(hKey, "MarginTop", gtk_page_setup_set_top_margin ); load_double(hKey, "MarginBottom", gtk_page_setup_set_bottom_margin ); load_double(hKey, "MarginLeft", gtk_page_setup_set_left_margin ); load_double(hKey, "MarginRight", gtk_page_setup_set_right_margin ); RegCloseKey(hKey); } #warning Work in progress RegCloseKey(registry); } #else GKeyFile * conf = get_application_keyfile(); GError * err = NULL; if(!gtk_print_settings_load_key_file(settings,conf,"print_settings",&err)) { g_warning("Error getting print settings: %s",err->message); g_error_free(err); err = NULL; } if(!gtk_page_setup_load_key_file(setup,conf,"page_setup",&err)) { g_warning("Error getting page setup: %s",err->message); g_error_free(err); err = NULL; } #endif } // Finish settings gtk_print_operation_set_print_settings(print,settings); gtk_print_operation_set_default_page_setup(print,setup); return print; } void print_all_action(GtkAction *action, GtkWidget *widget) { PRINT_INFO * info = NULL; GtkPrintOperation * print = begin_print_operation(action,widget,&info); trace("Action %s activated on widget %p print=%p",gtk_action_get_name(action),widget,print); lib3270_get_screen_size(info->session,&info->rows,&info->cols); info->all = 1; g_signal_connect(print,"begin_print",G_CALLBACK(begin_print),info); g_signal_connect(print,"draw_page",G_CALLBACK(draw_page),info); // Run Print dialog gtk_print_operation_run(print,GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,GTK_WINDOW(gtk_widget_get_toplevel(widget)),NULL); g_object_unref(print); } void print_selected_action(GtkAction *action, GtkWidget *widget) { PRINT_INFO * info = NULL; int start, end, rows; GtkPrintOperation * print = begin_print_operation(action,widget,&info);; trace("Action %s activated on widget %p",gtk_action_get_name(action),widget); if(lib3270_get_selected_addr(info->session,&start,&end)) { g_warning("Can't get selected addresses for action %s",gtk_action_get_name(action)); g_object_unref(print); return; } info->baddr = start; lib3270_get_screen_size(info->session,&rows,&info->cols); info->rows = ((end / info->cols) - (start / info->cols))+1; trace("First row: %d End row: %d Num rows: %d",(start / info->cols),(end / info->cols),info->rows); info->all = 0; g_signal_connect(print,"begin_print",G_CALLBACK(begin_print),info); g_signal_connect(print,"draw_page",G_CALLBACK(draw_page),info); // Run Print dialog gtk_print_operation_run(print,GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,GTK_WINDOW(gtk_widget_get_toplevel(widget)),NULL); g_object_unref(print); } void print_copy_action(GtkAction *action, GtkWidget *widget) { trace("Action %s activated on widget %p",gtk_action_get_name(action),widget); }