From 8cdc248c9769e50477679725f3d2c1d2af108a8b Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Tue, 6 Aug 2019 12:31:49 -0300 Subject: [PATCH] Refactoring "paste from file" method. --- src/dialogs/load.c | 333 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dialogs/popups.c | 31 +++++++++++++++++++++++++++++++ src/dialogs/print/print.c | 24 ++++++++---------------- src/dialogs/save/convenience.c | 1 - src/dialogs/save/private.h | 29 +++++++++++++++++++++++++++-- src/dialogs/save/save.c | 17 +++++------------ src/dialogs/transfer.c | 17 ++++++----------- src/filetransfer/activitylist.c | 17 ++++++----------- src/filetransfer/load.c | 21 +++++++-------------- src/filetransfer/save.c | 17 ++++++----------- src/include/internals.h | 2 ++ src/include/save.h | 31 ------------------------------- src/include/v3270.h | 1 + src/include/v3270/dialogs.h | 9 +++++++++ src/selection/text.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------ src/terminal/callbacks.c | 20 ++++++++++++++++++-- src/terminal/charset.c | 25 ++++++++----------------- src/testprogram/toolbar.c | 32 ++++++++++++++++++++------------ src/trace/trace.c | 24 ++++++++---------------- v3270.cbp | 3 +++ 20 files changed, 598 insertions(+), 240 deletions(-) create mode 100644 src/dialogs/load.c diff --git a/src/dialogs/load.c b/src/dialogs/load.c new file mode 100644 index 0000000..6a8d56a --- /dev/null +++ b/src/dialogs/load.c @@ -0,0 +1,333 @@ +/* + * "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., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + + + #include "private.h" + #include + #include + #include + #include + #include + #include + +/*--[ Widget definition ]----------------------------------------------------------------------------*/ + + typedef struct _V3270LoadDialog + { + GtkDialog parent; + + GtkWidget * terminal; + GtkWidget * filename; + GtkWidget * charset; + + } V3270LoadDialog; + + typedef struct _V3270LoadDialogClass + { + GtkDialogClass parent_class; + int dummy; + + } V3270LoadDialogClass; + + #define GTK_TYPE_V3270LoadDialog (V3270LoadDialog_get_type ()) + #define V3270_LOAD_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270LoadDialog, V3270LoadDialog)) + #define V3270LoadDialog_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_V3270Loadialog, V3270LoadDialogClass)) + #define IS_V3270LoadDialog(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_V3270LoadDialog)) + #define IS_V3270LoadDialog_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_V3270LoadDialog)) + #define V3270LoadDialog_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_V3270LoadDialog, V3270LoadDialogClass)) + + G_DEFINE_TYPE(V3270LoadDialog, V3270LoadDialog, GTK_TYPE_DIALOG); + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + + static void V3270LoadDialog_class_init(V3270LoadDialogClass G_GNUC_UNUSED(*klass)) + { + + debug("%s",__FUNCTION__); + + } + + static void cancel_operation(GtkButton G_GNUC_UNUSED(*button), GtkDialog *dialog) + { + gtk_dialog_response(dialog,GTK_RESPONSE_CANCEL); + } + + static void apply_operation(GtkButton G_GNUC_UNUSED(*button), GtkDialog *dialog) + { + gtk_dialog_response(dialog,GTK_RESPONSE_APPLY); + } + +#ifdef WIN32 +static void icon_press(GtkEntry G_GNUC_UNUSED(*entry), G_GNUC_UNUSED GtkEntryIconPosition icon_pos, G_GNUC_UNUSED GdkEvent *event, V3270LoadDialog *widget) +{ + g_autofree gchar *filename = + v3270_select_file( + GTK_WIDGET(widget), + _( "Select file"), + _("Open"), + GTK_FILE_CHOOSER_ACTION_OPEN, + gtk_entry_get_text(GTK_ENTRY(widget->filename)), + N_("All files"), "*.*", + NULL + ); + + if(filename && *filename) { + gtk_entry_set_text(GTK_ENTRY(widget->filename),filename); + } + +} +#else +static void icon_press(GtkEntry *entry, G_GNUC_UNUSED GtkEntryIconPosition icon_pos, G_GNUC_UNUSED GdkEvent *event, V3270LoadDialog *widget) +{ + GtkWidget * dialog = + gtk_file_chooser_dialog_new( + _( "Select file"), + GTK_WINDOW(widget), + GTK_FILE_CHOOSER_ACTION_OPEN, + _("Cancel"), GTK_RESPONSE_CANCEL, + _("Open"), GTK_RESPONSE_ACCEPT, + NULL ); + + + gtk_window_set_deletable(GTK_WINDOW(dialog),FALSE); + g_signal_connect(G_OBJECT(dialog),"close",G_CALLBACK(v3270_dialog_close),NULL); + + const gchar *filename = gtk_entry_get_text(entry); + + if(filename && *filename) + gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),filename); + + if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) + gtk_entry_set_text(entry,gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))); + + gtk_widget_destroy(dialog); + + } +#endif // _WIN32 + + static void V3270LoadDialog_init(V3270LoadDialog *dialog) + { + // 0--------1---------------------2-------3--------------------4 + // 0 - Filename xxxxxxxxx.xxxxxxxxx.xxxxxxxxx.xxxxxxxxx.xxxxxxxxx. x + // 1 - Charset xxxxxxxxx.xxxxxxxxx. Format: xxxxxxxxx.xxxxxxxxx. + + + gtk_window_set_deletable(GTK_WINDOW(dialog),FALSE); + + // Setup visual elements + // https://developer.gnome.org/hig/stable/visual-layout.html.en + GtkWidget *widget; + GtkWidget *button; + + GtkBox * box = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))); + gtk_window_set_resizable(GTK_WINDOW(dialog),FALSE); + gtk_container_set_border_width(GTK_CONTAINER(box),18); + + GtkGrid * grid = GTK_GRID(gtk_grid_new()); + gtk_grid_set_row_spacing(GTK_GRID(grid),6); + gtk_grid_set_column_spacing(GTK_GRID(grid),12); + gtk_box_pack_start(box,GTK_WIDGET(grid),TRUE,TRUE,2); + + // Filename entry + { + dialog->filename = gtk_entry_new(); + gtk_widget_set_hexpand(GTK_WIDGET(dialog->filename),TRUE); + + widget = gtk_label_new_with_mnemonic(_("_Filename")); + gtk_widget_set_halign(widget,GTK_ALIGN_END); + gtk_widget_set_valign(widget,GTK_ALIGN_CENTER); + gtk_grid_attach(grid,widget,0,0,1,1); + gtk_label_set_mnemonic_widget(GTK_LABEL(widget),dialog->filename); + + gtk_entry_set_icon_from_icon_name(GTK_ENTRY(dialog->filename),GTK_ENTRY_ICON_SECONDARY,"document-open"); + gtk_entry_set_icon_activatable(GTK_ENTRY(dialog->filename),GTK_ENTRY_ICON_SECONDARY,TRUE); + gtk_entry_set_icon_tooltip_text(GTK_ENTRY(dialog->filename),GTK_ENTRY_ICON_SECONDARY,_("Select file")); + g_signal_connect(G_OBJECT(dialog->filename),"icon-press",G_CALLBACK(icon_press),dialog); + + gtk_entry_set_width_chars(GTK_ENTRY(dialog->filename),60); + gtk_entry_set_max_length(GTK_ENTRY(dialog->filename),PATH_MAX); + gtk_grid_attach(grid,GTK_WIDGET(dialog->filename),1,0,3,1); + } + + // Charset drop-down + { + widget = gtk_label_new_with_mnemonic (_("C_haracter Coding")); + gtk_widget_set_halign(widget,GTK_ALIGN_END); + gtk_widget_set_valign(widget,GTK_ALIGN_CENTER); + gtk_grid_attach(grid,widget,0,1,1,1); + + dialog->charset = v3270_charset_combo_box_new(); + gtk_grid_attach(grid,dialog->charset,1,1,1,1); + + } + + + // Buttons + // https://developer.gnome.org/icon-naming-spec/ +#ifdef _WIN32 + widget = NULL; +#elif GTK_CHECK_VERSION(3,14,0) + widget = gtk_dialog_get_header_bar(GTK_DIALOG(dialog)); +#else + widget = NULL; +#endif // GTK(3,14,0) + + if(widget) + { + // Have header bar + button = gtk_button_new_with_mnemonic(_("_Cancel")); + gtk_widget_set_tooltip_markup(button,_("Click to cancel operation")); + gtk_header_bar_pack_start(GTK_HEADER_BAR(widget),button); + g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(cancel_operation),dialog); + + button = gtk_button_new_with_mnemonic(_("_Load")); + gtk_widget_set_tooltip_markup(button,_("Click to load file")); + gtk_header_bar_pack_end(GTK_HEADER_BAR(widget),button); + g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(apply_operation),dialog); + } + else + { + gtk_box_set_spacing( + GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), + 18 + ); + + gtk_dialog_add_buttons( + GTK_DIALOG (dialog), + _("_Cancel"), GTK_RESPONSE_CANCEL, + _("_Load"), GTK_RESPONSE_APPLY, + NULL + ); + } + + } + + GtkWidget * v3270_load_dialog_new(GtkWidget *widget, const gchar *filename) + { + g_return_val_if_fail(GTK_IS_V3270(widget),NULL); + + gboolean use_header; + g_object_get(gtk_settings_get_default(), "gtk-dialogs-use-header", &use_header, NULL); + + // Create dialog + V3270LoadDialog * dialog = V3270_LOAD_DIALOG( + g_object_new( + GTK_TYPE_V3270LoadDialog, + "use-header-bar", (use_header ? 1 : 0), + NULL) + ); + + dialog->terminal = widget; + + gtk_window_set_title(GTK_WINDOW(dialog),_("Paste from file")); + + if(filename) + gtk_entry_set_text(GTK_ENTRY(dialog->filename),filename); + + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(gtk_widget_get_toplevel(widget))); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + gtk_window_set_destroy_with_parent(GTK_WINDOW(dialog), TRUE); + + return GTK_WIDGET(dialog); + } + + void v3270_load_dialog_apply(GtkWidget *widget, GError **error) + { + V3270LoadDialog * dialog = V3270_LOAD_DIALOG(widget); + + debug("%s error=%p",__FUNCTION__,*error); + + if(!v3270_is_connected(dialog->terminal)) + { + *error = g_error_new(g_quark_from_static_string(PACKAGE_NAME),ENOTCONN,"%s",strerror(ENOTCONN)); + return; + } + + // Load file + g_autofree gchar * contents = NULL; + g_file_get_contents( + gtk_entry_get_text(GTK_ENTRY(dialog->filename)), + &contents, + NULL, + error + ); + + // Got contents, check for charset conversion. + g_autofree gchar * converted = + v3270_convert_to_3270_charset( + dialog->terminal, + contents, + gtk_combo_box_get_active_id(GTK_COMBO_BOX(dialog->charset)), + error + ); + + if(*error) + return; + + gboolean next = lib3270_paste( + v3270_get_session(dialog->terminal), + (unsigned char *) converted + ) ? TRUE : FALSE; + + debug("next=%s",next ? "YES" : "NO"); + + g_signal_emit( + dialog->terminal, + v3270_widget_signal[V3270_SIGNAL_PASTENEXT], + 0, + next + ); + + } + + void v3270_load_dialog_run(GtkWidget *widget) + { + debug("%s",__FUNCTION__); + if(gtk_dialog_run(GTK_DIALOG(widget)) == GTK_RESPONSE_APPLY) + { + GError * error = NULL; + v3270_load_dialog_apply(widget,&error); + + if(error) + { + v3270_popup_gerror( + widget, + error, + NULL, + _("Can't open %s"),gtk_entry_get_text(GTK_ENTRY(V3270_LOAD_DIALOG(widget)->filename)) + ); + g_error_free(error); + } + + } + debug("%s",__FUNCTION__); + + } + + diff --git a/src/dialogs/popups.c b/src/dialogs/popups.c index c0361df..be14564 100644 --- a/src/dialogs/popups.c +++ b/src/dialogs/popups.c @@ -100,3 +100,34 @@ } + void v3270_popup_gerror(GtkWidget *widget, GError *error, const gchar *title, const gchar *fmt, ...) + { + + // Format message. + va_list arg_ptr; + va_start(arg_ptr, fmt); + g_autofree gchar *text = g_strdup_vprintf(fmt,arg_ptr); + va_end(arg_ptr); + + GtkWidget *dialog = gtk_message_dialog_new( + GTK_WINDOW(gtk_widget_get_toplevel(widget)), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_OK, + "%s",text + ); + + if(title) + gtk_window_set_title(GTK_WINDOW(dialog), title); + else + gtk_window_set_title(GTK_WINDOW(dialog), (title ? title : _("Operation failed"))); + + if(error) + gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),"%s",error->message); + + g_signal_connect(dialog,"close",G_CALLBACK(gtk_widget_destroy),NULL); + g_signal_connect(dialog,"response",G_CALLBACK(gtk_widget_destroy),NULL); + + gtk_widget_show_all(dialog); + + } diff --git a/src/dialogs/print/print.c b/src/dialogs/print/print.c index 464e519..b9a797b 100644 --- a/src/dialogs/print/print.c +++ b/src/dialogs/print/print.c @@ -30,6 +30,7 @@ #include "private.h" #include #include + #include #include G_DEFINE_TYPE(V3270PrintOperation, V3270PrintOperation, GTK_TYPE_PRINT_OPERATION); @@ -45,25 +46,16 @@ if(result == GTK_PRINT_OPERATION_RESULT_ERROR) { - GError * err = NULL; + GError * err = NULL; gtk_print_operation_get_error(prt,&err); - GtkWidget *dialog = gtk_message_dialog_new_with_markup( - GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(operation->widget))), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - "%s",_( "Print operation failed" ) - ); - - g_warning("%s",err->message); - - gtk_window_set_title(GTK_WINDOW(dialog),_("Error")); - - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),"%s",err->message); - - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); + v3270_popup_gerror( + GTK_WIDGET(operation->widget), + err, + NULL, + "%s",_( "Print operation failed" ) + ); g_error_free(err); diff --git a/src/dialogs/save/convenience.c b/src/dialogs/save/convenience.c index 50f1ebc..6242fd4 100644 --- a/src/dialogs/save/convenience.c +++ b/src/dialogs/save/convenience.c @@ -72,7 +72,6 @@ return errno = ENOTCONN; } - lib3270_trace_event(v3270_get_session(widget),"save action activated (type=%d)",(int) mode); int rc = lib3270_save(v3270_get_session(widget),mode,filename); if(!rc) diff --git a/src/dialogs/save/private.h b/src/dialogs/save/private.h index d7353e6..58419d1 100644 --- a/src/dialogs/save/private.h +++ b/src/dialogs/save/private.h @@ -27,14 +27,27 @@ * */ + #include + #define ENABLE_NLS + + #ifndef GETTEXT_PACKAGE + #define GETTEXT_PACKAGE PACKAGE_NAME + #endif + + #include + #include + #include + #include #include - #include + #include #include #include #include /*--[ Widget definition ]----------------------------------------------------------------------------*/ + G_BEGIN_DECLS + struct _V3270SaveDialog { GtkDialog parent; @@ -54,7 +67,19 @@ }; -/*--[ Prototypes ]-----------------------------------------------------------------------------------*/ +/*--[ Save Dialog Widget ]---------------------------------------------------------------------------*/ + + #define GTK_TYPE_V3270SaveDialog (V3270SaveDialog_get_type ()) + #define V3270_SAVE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270SaveDialog, V3270SaveDialog)) + #define V3270SaveDialog_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_V3270SaveDialog, V3270SaveDialogClass)) + #define IS_V3270SaveDialog(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_V3270SaveDialog)) + #define IS_V3270SaveDialog_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_V3270SaveDialog)) + #define V3270SaveDialog_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_V3270SaveDialog, V3270SaveDialogClass)) + + typedef struct _V3270SaveDialog V3270SaveDialog; + typedef struct _V3270SaveDialogClass V3270SaveDialogClass; + + G_END_DECLS diff --git a/src/dialogs/save/save.c b/src/dialogs/save/save.c index 958fb5d..ce66c4c 100644 --- a/src/dialogs/save/save.c +++ b/src/dialogs/save/save.c @@ -447,21 +447,14 @@ static void icon_press(GtkEntry *entry, G_GNUC_UNUSED GtkEntryIconPosition icon_ if(error) { - GtkWidget *popup = gtk_message_dialog_new_with_markup( - GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - _("Can't save %s"),gtk_entry_get_text(GTK_ENTRY(V3270_SAVE_DIALOG(widget)->filename)) + v3270_popup_gerror( + widget, + error, + NULL, + _("Can't save %s"),gtk_entry_get_text(GTK_ENTRY(V3270_SAVE_DIALOG(widget)->filename)) ); - gtk_window_set_title(GTK_WINDOW(popup),_("Operation has failed")); - - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message); g_error_free(error); - - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); - } } diff --git a/src/dialogs/transfer.c b/src/dialogs/transfer.c index 8f4876b..db947c3 100644 --- a/src/dialogs/transfer.c +++ b/src/dialogs/transfer.c @@ -39,6 +39,7 @@ #include #include + #include /*--[ Implement ]------------------------------------------------------------------------------------*/ @@ -89,21 +90,15 @@ static void save_activity_clicked(GtkWidget *button, GObject *activity) if(!g_file_set_contents(filename,text,-1,&error)) { - GtkWidget *popup = gtk_message_dialog_new_with_markup( - GTK_WINDOW(gtk_widget_get_toplevel(button)), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - _("Can't save %s"),filename + v3270_popup_gerror( + button, + error, + NULL, + _("Can't save %s"),filename ); - gtk_window_set_title(GTK_WINDOW(popup),_("Operation has failed")); - - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message); g_error_free(error); - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); - } } diff --git a/src/filetransfer/activitylist.c b/src/filetransfer/activitylist.c index b8540f2..361fa86 100644 --- a/src/filetransfer/activitylist.c +++ b/src/filetransfer/activitylist.c @@ -28,6 +28,7 @@ */ #include + #include #include "private.h" #include "marshal.h" @@ -430,21 +431,15 @@ if(!g_file_set_contents(list->filename,text,-1,&error)) { - GtkWidget *popup = gtk_message_dialog_new_with_markup( - GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - _("Can't save %s"),list->filename + v3270_popup_gerror( + widget, + error, + NULL, + _("Can't save %s"),list->filename ); - gtk_window_set_title(GTK_WINDOW(popup),_("Operation has failed")); - - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message); g_error_free(error); - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); - } diff --git a/src/filetransfer/load.c b/src/filetransfer/load.c index 216c029..5d478f3 100644 --- a/src/filetransfer/load.c +++ b/src/filetransfer/load.c @@ -32,6 +32,7 @@ #include #include + #include /*--[ Statics ]--------------------------------------------------------------------------------------*/ @@ -263,23 +264,15 @@ LIB3270_EXPORT void v3270ft_load(GtkWidget *widget,const gchar *filename) { if(error) { - GtkWidget *popup = gtk_message_dialog_new_with_markup( - GTK_WINDOW(widget), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - _("Can't load %s"),filename); - - gtk_window_set_title(GTK_WINDOW(popup),_("Operation has failed")); - - if(error->message && *error->message) { - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message); - } + v3270_popup_gerror( + widget, + error, + NULL, + _("Can't load %s"),filename + ); g_error_free(error); - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); - } } diff --git a/src/filetransfer/save.c b/src/filetransfer/save.c index 908de17..7e36dad 100644 --- a/src/filetransfer/save.c +++ b/src/filetransfer/save.c @@ -109,20 +109,15 @@ static const gchar * getNameByFlag(LIB3270_FT_OPTION opt, LIB3270_FT_OPTION mask if(!g_file_set_contents(filename,text,-1,&error)) { - GtkWidget *popup = gtk_message_dialog_new_with_markup( - GTK_WINDOW(widget), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE, - _("Can't save %s"),filename); + v3270_popup_gerror( + widget, + error, + NULL, + _("Can't save %s"),filename + ); - gtk_window_set_title(GTK_WINDOW(popup),_("Operation has failed")); - - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message); g_error_free(error); - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); - } g_free(text); diff --git a/src/include/internals.h b/src/include/internals.h index 48af392..d5a0d89 100644 --- a/src/include/internals.h +++ b/src/include/internals.h @@ -107,6 +107,8 @@ G_GNUC_INTERNAL void v3270_dialog_close(GtkDialog *dialog, gpointer user_data); + G_GNUC_INTERNAL gchar * v3270_convert_to_3270_charset(GtkWidget *widget, const gchar *text, const gchar *encoding, GError **error); + /*--[ Internal Widgets & Tools ]---------------------------------------------------------------------*/ diff --git a/src/include/save.h b/src/include/save.h index cce319d..ca01098 100644 --- a/src/include/save.h +++ b/src/include/save.h @@ -31,37 +31,6 @@ #define V3270SAVE_H_INCLUDED 1 - #include - #define ENABLE_NLS - #ifndef GETTEXT_PACKAGE - #define GETTEXT_PACKAGE PACKAGE_NAME - #endif - - #include - #include - #include - #include - - G_BEGIN_DECLS - -/*--[ Progress widget ]------------------------------------------------------------------------------*/ - - #define GTK_TYPE_V3270SaveDialog (V3270SaveDialog_get_type ()) - #define V3270_SAVE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_V3270SaveDialog, V3270SaveDialog)) - #define V3270SaveDialog_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_V3270SaveDialog, V3270SaveDialogClass)) - #define IS_V3270SaveDialog(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_V3270SaveDialog)) - #define IS_V3270SaveDialog_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_V3270SaveDialog)) - #define V3270SaveDialog_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_V3270SaveDialog, V3270SaveDialogClass)) - - typedef struct _V3270SaveDialog V3270SaveDialog; - typedef struct _V3270SaveDialogClass V3270SaveDialogClass; - -/*--[ Prototipes ]-----------------------------------------------------------------------------------*/ - - GtkWidget * v3270_save_dialog_new(GtkWidget *widget, LIB3270_CONTENT_OPTION mode, const gchar *filename); - void v3270_save_dialog_run(GtkWidget *widget); - - G_END_DECLS #endif // V3270SAVE_H_INCLUDED diff --git a/src/include/v3270.h b/src/include/v3270.h index 6fbbd07..48e335d 100644 --- a/src/include/v3270.h +++ b/src/include/v3270.h @@ -210,6 +210,7 @@ LIB3270_EXPORT void v3270_paste(GtkWidget *widget); LIB3270_EXPORT void v3270_paste_text(GtkWidget *widget); + LIB3270_EXPORT void v3270_paste_from_file(GtkWidget *widget); LIB3270_EXPORT void v3270_input_text(GtkWidget *widget, const gchar *text, const gchar *encoding); // Colors diff --git a/src/include/v3270/dialogs.h b/src/include/v3270/dialogs.h index e5d8b89..adc38d8 100644 --- a/src/include/v3270/dialogs.h +++ b/src/include/v3270/dialogs.h @@ -39,6 +39,15 @@ LIB3270_EXPORT GtkWidget * v3270_dialog_new(GtkWidget *widget, const gchar *title, const gchar *apply); LIB3270_EXPORT void v3270_error_popup(GtkWidget *widget, const gchar *title, const gchar *summary, const gchar *body); + LIB3270_EXPORT GtkWidget * v3270_save_dialog_new(GtkWidget *widget, LIB3270_CONTENT_OPTION mode, const gchar *filename); + LIB3270_EXPORT void v3270_save_dialog_run(GtkWidget *widget); + + LIB3270_EXPORT GtkWidget * v3270_load_dialog_new(GtkWidget *widget, const gchar *filename); + LIB3270_EXPORT void v3270_load_dialog_run(GtkWidget *widget); + + LIB3270_EXPORT void v3270_popup_gerror(GtkWidget *widget, GError *error, const gchar *title, const gchar *fmt, ...) G_GNUC_PRINTF(4,5); + + G_END_DECLS #endif // V3270_DIALOGS_H_INCLUDED diff --git a/src/selection/text.c b/src/selection/text.c index e85626d..34b932a 100644 --- a/src/selection/text.c +++ b/src/selection/text.c @@ -29,6 +29,7 @@ #include #include + #include /*--[ Implement ]------------------------------------------------------------------------------------*/ @@ -71,48 +72,50 @@ gchar * v3270_get_copy_as_text(v3270 * terminal, const gchar *encoding) return v3270_get_selection_as_text(terminal, terminal->selection.blocks, encoding, FALSE); } -LIB3270_EXPORT void v3270_input_text(GtkWidget *widget, const gchar *text, const gchar *encoding) +gchar * v3270_convert_to_3270_charset(GtkWidget *widget, const gchar *text, const gchar *encoding, GError **error) { - gchar * buffer = NULL; - H3270 * session = v3270_get_session(widget); - const gchar * charset = lib3270_get_display_charset(session); - gboolean next; + if(*error || !text) + return NULL; - if(!text) - return; - else if(g_ascii_strcasecmp(encoding,charset)) - buffer = g_convert(text, -1, charset, encoding, NULL, NULL, NULL); - else - buffer = g_strdup(text); - - if(!buffer) - { - /* Conversion failed, update special chars and try again */ - size_t f; - - static const struct _xlat - { - const gchar *from; - const gchar *to; - } xlat[] = - { - { "–", "-" }, - { "→", "->" }, - { "←", "<-" }, - { "©", "(c)" }, - { "↔", "<->" }, - { "™", "(TM)" }, - { "®", "(R)" }, - { "“", "\"" }, - { "”", "\"" }, - { "…", "..." }, - { "•", "*" }, - { "․", "." }, - { "·", "*" }, - - }; - - gchar *string = g_strdup(text); + const gchar * charset = lib3270_get_display_charset(v3270_get_session(widget)); + if(!encoding || (g_ascii_strcasecmp(encoding,charset) == 0)) + { + // No conversion needed. + return g_strdup(text); + } + + gchar *converted = g_convert(text, -1, charset, encoding, NULL, NULL, NULL); + if(converted) + return converted; + + // Conversion failed, update UTF-8 special chars and try again + if(!g_ascii_strcasecmp(encoding,"UTF-8")) + { + size_t f; + + static const struct _xlat + { + const gchar *from; + const gchar *to; + } xlat[] = + { + { "–", "-" }, + { "→", "->" }, + { "←", "<-" }, + { "©", "(c)" }, + { "↔", "<->" }, + { "™", "(TM)" }, + { "®", "(R)" }, + { "“", "\"" }, + { "”", "\"" }, + { "…", "..." }, + { "•", "*" }, + { "․", "." }, + { "·", "*" }, + + }; + + g_autofree gchar *string = g_strdup(text); // FIXME (perry#1#): Is there any better way for a "sed" here? for(f=0;fmessage, ln[f]); - g_error_free(error); - error = NULL; - } - - gtk_dialog_run(GTK_DIALOG (dialog)); - gtk_widget_destroy(dialog); - - break; - } - else - { - g_free(str); - } - + g_strfreev(ln); + return NULL; } - g_strfreev(ln); + + g_free(str); } + g_strfreev(ln); + + } + */ + + // Can't convert, use fallbacks + return g_convert_with_fallback( + text, + -1, + charset, + encoding, + " ", + NULL, + NULL, + error + ); +} - g_free(string); - } +LIB3270_EXPORT void v3270_input_text(GtkWidget *widget, const gchar *text, const gchar *encoding) +{ + GError * error = NULL; + g_autofree gchar * buffer = v3270_convert_to_3270_charset(widget,text,encoding,&error); if(buffer) { @@ -187,17 +193,27 @@ LIB3270_EXPORT void v3270_input_text(GtkWidget *widget, const gchar *text, const *ptr = ' '; } } - else + + if(error) { g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_PASTENEXT], 0, FALSE); + v3270_popup_gerror(widget,error,NULL,"%s",_("Can't paste text")); + g_error_free(error); return; } - next = lib3270_paste(session,(unsigned char *) buffer) ? TRUE : FALSE; - - g_free(buffer); - - g_signal_emit(widget,v3270_widget_signal[V3270_SIGNAL_PASTENEXT], 0, next); + // Do paste. + gboolean next = lib3270_paste( + v3270_get_session(widget), + (unsigned char *) buffer + ) ? TRUE : FALSE; + + g_signal_emit( + v3270_get_session(widget), + v3270_widget_signal[V3270_SIGNAL_PASTENEXT], + 0, + next + ); } diff --git a/src/terminal/callbacks.c b/src/terminal/callbacks.c index 3b9f469..023c533 100644 --- a/src/terminal/callbacks.c +++ b/src/terminal/callbacks.c @@ -35,7 +35,7 @@ #include #include - #include + #include #include #include @@ -337,7 +337,7 @@ static int save(H3270 *session, LIB3270_CONTENT_OPTION mode, const char *filenam GtkWidget * widget = GTK_WIDGET(lib3270_get_user_data(session)); if(!GTK_IS_V3270(widget)) - return EINVAL; + return errno = EINVAL; GtkWidget *dialog = v3270_save_dialog_new(widget,mode,filename); gtk_widget_show_all(dialog); @@ -347,6 +347,21 @@ static int save(H3270 *session, LIB3270_CONTENT_OPTION mode, const char *filenam return 0; } +static int load(H3270 *session, const char *filename) +{ + GtkWidget * widget = GTK_WIDGET(lib3270_get_user_data(session)); + + if(!GTK_IS_V3270(widget)) + return errno = EINVAL; + + GtkWidget *dialog = v3270_load_dialog_new(widget,filename); + gtk_widget_show_all(dialog); + v3270_load_dialog_run(dialog); + gtk_widget_destroy(dialog); + + return 0; +} + static void popup_handler(H3270 *session, LIB3270_NOTIFY type, const char *title, const char *msg, const char *fmt, va_list args) { GtkWidget *terminal = (GtkWidget *) lib3270_get_user_data(session); @@ -493,6 +508,7 @@ static void popup_handler(H3270 *session, LIB3270_NOTIFY type, const char *title cbk->update_ssl = update_ssl; cbk->print = print; cbk->save = save; + cbk->load = load; cbk->popup_ssl_error = popup_ssl_error; } diff --git a/src/terminal/charset.c b/src/terminal/charset.c index 5a96cf2..63d980f 100644 --- a/src/terminal/charset.c +++ b/src/terminal/charset.c @@ -32,6 +32,7 @@ #include #include #include + #include #define ERROR_DOMAIN g_quark_from_static_string(PACKAGE_NAME) @@ -454,27 +455,17 @@ if(error) { - GtkWidget * dialog; - gchar * name = g_path_get_basename(path); + g_autofree gchar * name = g_path_get_basename(path); - dialog = gtk_message_dialog_new( NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_WARNING, - GTK_BUTTONS_OK, - _( "Can't parse %s" ), name); - - g_free(name); - - gtk_window_set_title(GTK_WINDOW(dialog), _( "Remap Failed" ) ); - - if(error->message) - gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", error->message); + v3270_popup_gerror( + widget, + error, + _( "Remap Failed" ), + _( "Can't parse %s" ), name + ); g_error_free(error); - gtk_dialog_run(GTK_DIALOG (dialog)); - gtk_widget_destroy(dialog); - } else { H3270 * hSession = v3270_get_session(widget); diff --git a/src/testprogram/toolbar.c b/src/testprogram/toolbar.c index 4c9d26b..f1f33fe 100644 --- a/src/testprogram/toolbar.c +++ b/src/testprogram/toolbar.c @@ -59,11 +59,16 @@ lib3270_disconnect(v3270_get_session(terminal)); } -static void save_all_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) + static void save_all_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) { lib3270_save_all(v3270_get_session(terminal),NULL); } + static void load_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *terminal) + { + lib3270_load(v3270_get_session(terminal),NULL); + } + static void ft_clicked(GtkButton *button, GtkWidget *terminal) { v3270_error_popup(terminal,"title","summary","body"); @@ -176,25 +181,28 @@ static void save_all_clicked(GtkButton G_GNUC_UNUSED(*button), GtkWidget *termin // https://specifications.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html static const struct _buttons { - const gchar * icon; + const gchar * icon; // https://specifications.freedesktop.org/icon-naming-spec/latest/ar01s04.html GCallback callback; const gchar * tooltip; } buttons[] = { - { "gtk-connect", G_CALLBACK(connect_clicked), "Connect to host" }, - { "gtk-disconnect", G_CALLBACK(disconnect_clicked), "Disconnect from host" }, - { "gtk-select-color", G_CALLBACK(color_clicked), "Edit or change color scheme" }, - { "gtk-home", G_CALLBACK(host_clicked), "Configure host" }, - { "gtk-print", G_CALLBACK(print_clicked), "Print screen contents" }, - { "gtk-harddisk", G_CALLBACK(ft_clicked), "Open file transfer dialog" }, - { "gtk-copy", G_CALLBACK(copy_clicked), "Copy data" }, - { "gtk-paste", G_CALLBACK(paste_clicked), "Paste data" }, - { "gtk-save", G_CALLBACK(save_all_clicked), "Save screen" } + { "gtk-connect", G_CALLBACK(connect_clicked), "Connect to host" }, + { "gtk-disconnect", G_CALLBACK(disconnect_clicked), "Disconnect from host" }, + { "gtk-select-color", G_CALLBACK(color_clicked), "Edit or change color scheme" }, + { "network-server", G_CALLBACK(host_clicked), "Configure host" }, + { "gtk-print", G_CALLBACK(print_clicked), "Print screen contents" }, + { "gtk-harddisk", G_CALLBACK(ft_clicked), "Open file transfer dialog" }, + { "gtk-copy", G_CALLBACK(copy_clicked), "Copy data" }, + { "gtk-paste", G_CALLBACK(paste_clicked), "Paste data" }, + { "document-save", G_CALLBACK(save_all_clicked), "Save screen" }, + { "document-open", G_CALLBACK(load_clicked), "Paste file" }, + }; GtkWidget * toolbar = gtk_toolbar_new(); for(f = 0; f < G_N_ELEMENTS(buttons); f++) { - GtkWidget * button = GTK_WIDGET(gtk_tool_button_new_from_stock(buttons[f].icon)); + GtkWidget * button = gtk_tool_button_new(gtk_image_new_from_icon_name(buttons[f].icon,GTK_ICON_SIZE_SMALL_TOOLBAR),"-"); + gtk_widget_set_tooltip_markup(button,buttons[f].tooltip); g_signal_connect(G_OBJECT(button),"clicked",buttons[f].callback,terminal); gtk_toolbar_insert(GTK_TOOLBAR(toolbar),GTK_TOOL_ITEM(button),-1); diff --git a/src/trace/trace.c b/src/trace/trace.c index 010c45b..63d0b19 100644 --- a/src/trace/trace.c +++ b/src/trace/trace.c @@ -50,6 +50,7 @@ #include #include #include + #include #include #if defined( HAVE_SYSLOG ) @@ -443,23 +444,14 @@ if(error) { - GtkWidget *popup = - gtk_message_dialog_new_with_markup( - GTK_WINDOW(gtk_widget_get_toplevel(widget)), - GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - _( "Can't save %s" ), - filename - ); - - gtk_window_set_title(GTK_WINDOW(popup),_("Can't save file")); - - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message); - g_error_free(error); + v3270_popup_gerror( + widget, + error, + NULL, + _( "Can't save %s" ), filename + ); - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); + g_error_free(error); } diff --git a/v3270.cbp b/v3270.cbp index 336ce2b..a3a7819 100644 --- a/v3270.cbp +++ b/v3270.cbp @@ -60,6 +60,9 @@ + + -- libgit2 0.21.2