From 820c86c26cd7812f410c7a70067b9e7e7d5433c6 Mon Sep 17 00:00:00 2001 From: Perry Werneck Date: Mon, 5 Aug 2019 14:11:35 -0300 Subject: [PATCH] Small adjustments in the trace window. --- src/include/v3270.h | 1 - src/include/v3270/trace.h | 2 ++ src/testprogram/testprogram.c | 3 +++ src/trace/trace.c | 485 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/trace/tracewindow.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/trace/widget.c | 553 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- v3270.cbp | 5 ++++- 7 files changed, 636 insertions(+), 555 deletions(-) create mode 100644 src/trace/trace.c create mode 100644 src/trace/tracewindow.c delete mode 100644 src/trace/widget.c diff --git a/src/include/v3270.h b/src/include/v3270.h index 0f2dc60..6fbbd07 100644 --- a/src/include/v3270.h +++ b/src/include/v3270.h @@ -165,7 +165,6 @@ #endif // v3270_char LIB3270_EXPORT GtkWidget * v3270_new(void); - LIB3270_EXPORT GtkWidget * v3270_trace_window_new(GtkWidget *widget, const gchar *header); LIB3270_EXPORT GType v3270_get_type(void); LIB3270_EXPORT void v3270_reload(GtkWidget * widget); LIB3270_EXPORT void v3270_set_font_family(GtkWidget *widget, const gchar *name); diff --git a/src/include/v3270/trace.h b/src/include/v3270/trace.h index 48c5b24..b80d523 100644 --- a/src/include/v3270/trace.h +++ b/src/include/v3270/trace.h @@ -55,6 +55,8 @@ LIB3270_EXPORT void v3270_trace_save(GtkWidget *widget); LIB3270_EXPORT void v3270_trace_select_file(GtkWidget *widget); + LIB3270_EXPORT GtkWidget * v3270_trace_window_new(GtkWidget *widget, const gchar *header); + G_END_DECLS #endif // V3270_H_INCLUDED diff --git a/src/testprogram/testprogram.c b/src/testprogram/testprogram.c index 06a816b..a542c47 100644 --- a/src/testprogram/testprogram.c +++ b/src/testprogram/testprogram.c @@ -67,9 +67,12 @@ } // Create trace window + /* { gtk_notebook_append_page(GTK_NOTEBOOK(notebook),v3270_trace_new(terminal),gtk_label_new("Trace")); } + */ + v3270_trace_window_new(terminal,NULL); // Setup and show main window gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER); diff --git a/src/trace/trace.c b/src/trace/trace.c new file mode 100644 index 0000000..a77f72d --- /dev/null +++ b/src/trace/trace.c @@ -0,0 +1,485 @@ +/* + * "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 trace.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) + * + */ + +/** + * SECTION:V3270Trace + * @Short_description: A trace monitor widget. + * @Title: V3270Trace + * + * The #V3270Trace shows a text area with the lib3270 trace output. + * + */ + + #include + + #define ENABLE_NLS + #define GETTEXT_PACKAGE PACKAGE_NAME + + #include + #include + + #include + #include + #include + #include + #include + #include + #include + +#if defined( HAVE_SYSLOG ) + #include +#endif // HAVE_SYSLOG + +/*--[ Widget definition ]----------------------------------------------------------------------------*/ + + G_BEGIN_DECLS + + struct _V3270TraceClass + { + GtkBoxClass parent_class; + + }; + + struct _V3270Trace + { + GtkBox parent; + H3270 * hSession; ///< @brief TN3270 Session. + GtkWidget * terminal; ///< @brief V3270 Widget. + GtkScrolledWindow * scroll; + + GtkTextView * view; ///< @brief Text view; + GtkTextBuffer * text; ///< @brief Trace window contents. + GtkEntry * entry; ///< @brief Command line entry. + GtkWidget * buttons; ///< @brief Button bar. + + gchar * filename; ///< @brief Selected file name. + + guint log_handler; ///< @brief GTK Log Handler. + + /// @brief lib3270's saved trace handler. + struct { + void (*handler)(H3270 *session, void *userdata, const char *fmt, va_list args); + void *userdata; + } trace; + + }; + + G_END_DECLS + + G_DEFINE_TYPE(V3270Trace, V3270Trace, GTK_TYPE_BOX); + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + + static void trace_handler(H3270 *hSession, void *userdata, const char *fmt, va_list args) + { + g_autofree gchar *ptr = g_strdup_vprintf(fmt,args); + g_autofree gchar * utftext = g_convert_with_fallback(ptr,-1,"UTF-8",lib3270_get_display_charset(hSession),"?",NULL,NULL,NULL); + + v3270_trace_append_text(GTK_WIDGET(userdata),utftext); + + } + + static void set_session(V3270Trace *widget, H3270 *hSession) + { + // Return if it's the same session. + if(widget->hSession == hSession) + return; + + debug("%s: Session changes %p -> %p", __FUNCTION__, widget->hSession, hSession); + + if(widget->hSession) { + lib3270_set_trace_handler(widget->hSession,widget->trace.handler,widget->trace.userdata); + } + + widget->hSession = hSession; + + if(hSession) { + lib3270_get_trace_handler(hSession,&widget->trace.handler,&widget->trace.userdata); + lib3270_set_trace_handler(hSession,trace_handler,(void *) widget); + } + + } + + static void finalize(GObject *object) + { + debug("V3270Trace::%s",__FUNCTION__); + + V3270Trace *trace = GTK_V3270_TRACE(object); + + if(trace->filename) + { + g_free(trace->filename); + trace->filename = NULL; + } + + if(trace->log_handler) + { + g_log_remove_handler(NULL,trace->log_handler); + trace->log_handler = 0; + } + + set_session(trace,NULL); + g_clear_object(&trace->terminal); + + G_OBJECT_CLASS(V3270Trace_parent_class)->finalize(object); + } + + static void V3270Trace_class_init(G_GNUC_UNUSED V3270TraceClass *klass) + { + G_OBJECT_CLASS(klass)->finalize = finalize; + } + + static void v3270_trace_execute(GtkWidget *widget, const gchar *cmd) + { + if(!*cmd) + return; + + v3270_trace_printf(widget, "%s\n",cmd); + + V3270Trace *trace = GTK_V3270_TRACE(widget); + + if(trace->terminal) + { + int rc = v3270_exec_command(trace->terminal,cmd); + if(rc) + v3270_trace_printf(widget, "rc=%d (%s)\n",rc,strerror(rc)); + } + else + { + v3270_trace_append_text(widget, "Can't execute command without an associated terminal"); + } + + gtk_entry_set_text(trace->entry, ""); + + } + + static void execute_command(GtkEntry *entry, G_GNUC_UNUSED GtkEntryIconPosition icon_pos, G_GNUC_UNUSED GdkEvent *event, GtkWidget *widget) + { + v3270_trace_execute(widget, gtk_entry_get_text(entry)); + } + + static void entry_activated(GtkEntry *entry, GtkWidget *widget) + { + v3270_trace_execute(widget, gtk_entry_get_text(entry)); + } + + static void log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, GtkWidget *widget) + { + #ifndef LOG_INFO + #define LOG_INFO 0 + #endif // LOG_INFO + + #ifndef LOG_ERR + #define LOG_ERR 0 + #endif // LOG_ERR + + #ifndef LOG_DEBUG + #define LOG_DEBUG 0 + #endif // LOG_DEBUG + + static const struct _logtype + { + GLogLevelFlags log_level; + const gchar * msg; + } logtype[] = + { + { G_LOG_FLAG_RECURSION, "recursion" }, + { G_LOG_FLAG_FATAL, "fatal error" }, + + /* GLib log levels */ + { G_LOG_LEVEL_ERROR, "error" }, + { G_LOG_LEVEL_CRITICAL, "critical error" }, + { G_LOG_LEVEL_WARNING, "warning" }, + { G_LOG_LEVEL_MESSAGE, "message" }, + { G_LOG_LEVEL_INFO, "info" }, + { G_LOG_LEVEL_DEBUG, "debug" }, + }; + + size_t f; + + for(f=0;fbuttons = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); + + gtk_button_box_set_layout(GTK_BUTTON_BOX(widget->buttons), GTK_BUTTONBOX_START); + gtk_box_set_spacing(GTK_BOX(widget->buttons),8); + + gtk_widget_set_valign(widget->buttons,GTK_ALIGN_START); + gtk_box_pack_start(GTK_BOX(widget),widget->buttons,FALSE,FALSE,4); + + } + + // Create text view + { + widget->scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL,NULL)); + gtk_scrolled_window_set_policy(widget->scroll,GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); + gtk_widget_set_vexpand(GTK_WIDGET(widget->scroll),TRUE); + gtk_widget_set_hexpand(GTK_WIDGET(widget->scroll),TRUE); + + gtk_box_pack_start(GTK_BOX(widget),GTK_WIDGET(widget->scroll),TRUE,TRUE,4); + + widget->view = GTK_TEXT_VIEW(gtk_text_view_new()); + +#if GTK_CHECK_VERSION(3,16,0) + gtk_text_view_set_monospace(widget->view,TRUE); +#endif // GTK_CHECK_VERSION + + widget->text = gtk_text_view_get_buffer(widget->view); + gtk_text_view_set_editable(widget->view, TRUE); + + gtk_container_add(GTK_CONTAINER(widget->scroll),GTK_WIDGET(widget->view)); + gtk_widget_set_can_default(GTK_WIDGET(widget->view),FALSE); + + } + + // Create command line + { + widget->entry = GTK_ENTRY(gtk_entry_new()); + + gtk_widget_set_can_default(GTK_WIDGET(widget->entry),TRUE); + gtk_widget_grab_focus(GTK_WIDGET(widget->entry)); + + gtk_entry_set_activates_default(widget->entry,TRUE); + gtk_widget_set_vexpand(GTK_WIDGET(widget->entry),FALSE); + gtk_widget_set_hexpand(GTK_WIDGET(widget->entry),TRUE); + + gtk_entry_set_icon_from_icon_name(widget->entry,GTK_ENTRY_ICON_SECONDARY,"system-run"); + gtk_entry_set_placeholder_text(widget->entry,_("Command to execute")); + + gtk_box_pack_end(GTK_BOX(widget),GTK_WIDGET(widget->entry),FALSE,FALSE,4); + + g_signal_connect(G_OBJECT(widget->entry),"icon-press",G_CALLBACK(execute_command),widget); + g_signal_connect(G_OBJECT(widget->entry),"activate",G_CALLBACK(entry_activated),widget); + + } + + // Grab GTK messages. + widget->log_handler = g_log_set_handler(NULL,G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,(GLogFunc) log_handler, widget); + + } + + + LIB3270_EXPORT GtkWidget * v3270_trace_new(GtkWidget *terminal) + { + g_return_val_if_fail(GTK_IS_V3270(terminal),NULL); + + V3270Trace * widget = GTK_V3270_TRACE(g_object_new(GTK_TYPE_V3270_TRACE, NULL)); + + // Set terminal widget + { + widget->terminal = terminal; + g_object_ref_sink(G_OBJECT(terminal)); + set_session(widget, v3270_get_session(widget->terminal)); + } + + // Create toggle buttons + { + size_t ix; + + static const LIB3270_TOGGLE toggles[] = { LIB3270_TOGGLE_DS_TRACE, LIB3270_TOGGLE_NETWORK_TRACE, LIB3270_TOGGLE_EVENT_TRACE, LIB3270_TOGGLE_SSL_TRACE, LIB3270_TOGGLE_SCREEN_TRACE}; + + for(ix = 0; ix < G_N_ELEMENTS(toggles); ix++) + { + GtkWidget * item = v3270_toggle_button_new(widget->terminal,toggles[ix]); + + gtk_widget_set_can_focus(item,FALSE); + gtk_widget_set_can_default(item,FALSE); + gtk_widget_set_focus_on_click(item,FALSE); + + gtk_box_pack_start(GTK_BOX(widget->buttons),item,FALSE,FALSE,4); + + } + } + + + return GTK_WIDGET(widget); + } + + struct _append_text + { + V3270Trace *widget; + gchar text[1]; + }; + + static gboolean bg_append_text(struct _append_text *cfg) + { + if(!GTK_IS_TEXT_BUFFER(cfg->widget->text)) + return FALSE; + + GtkTextIter itr; + gtk_text_buffer_get_end_iter(cfg->widget->text,&itr); + + if(g_utf8_validate(cfg->text,strlen(cfg->text),NULL)) + { + gtk_text_buffer_insert(cfg->widget->text,&itr,cfg->text,strlen(cfg->text)); + } + else + { + gtk_text_buffer_insert(cfg->widget->text,&itr,"** Invalid UTF8 String **",-1); + } + + // gtk_text_buffer_get_end_iter(cfg->widget->text,&itr); + // gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(cfg->widget->view), &itr, 0.0, FALSE, 0.0, 0.0); + + GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(cfg->widget->scroll); + gtk_adjustment_set_value(vadj,gtk_adjustment_get_upper(vadj)); + gtk_scrolled_window_set_vadjustment(cfg->widget->scroll, vadj); + + return FALSE; + + } + + LIB3270_EXPORT void v3270_trace_append_text(GtkWidget *widget, const gchar *text) + { + g_return_if_fail(GTK_IS_V3270_TRACE(widget)); + + // Enqueue update. + struct _append_text * cfg = g_malloc0(sizeof(struct _append_text)+strlen(text)+1); + cfg->widget = GTK_V3270_TRACE(widget); + strcpy(cfg->text,text); + + g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,(GSourceFunc) bg_append_text, cfg, g_free); + + } + + LIB3270_EXPORT void v3270_trace_vprintf(GtkWidget *widget, const char *fmt, va_list args) + { + g_autofree gchar * text = g_strdup_vprintf(fmt,args); + v3270_trace_append_text(widget,text); + } + + LIB3270_EXPORT void v3270_trace_printf(GtkWidget *widget, const char *fmt, ... ) + { + va_list arg_ptr; + va_start(arg_ptr, fmt); + v3270_trace_vprintf(widget,fmt,arg_ptr); + va_end(arg_ptr); + } + + const gchar * v3270_trace_get_filename(GtkWidget *widget) + { + g_return_val_if_fail(GTK_IS_V3270_TRACE(widget),NULL); + return GTK_V3270_TRACE(widget)->filename; + } + + LIB3270_EXPORT void v3270_trace_save(GtkWidget *widget) + { + const gchar *filename = v3270_trace_get_filename(widget); + V3270Trace * trace = GTK_V3270_TRACE(widget); + + if(filename) + { + GError * error = NULL; + gchar * text; + GtkTextIter start; + GtkTextIter end; + + gtk_text_buffer_get_start_iter(trace->text,&start); + gtk_text_buffer_get_end_iter(trace->text,&end); + text = gtk_text_buffer_get_text(trace->text,&start,&end,FALSE); + + g_file_set_contents(trace->filename,text,-1,&error); + + g_free(text); + + 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); + + gtk_dialog_run(GTK_DIALOG(popup)); + gtk_widget_destroy(popup); + + } + + } + + } + + LIB3270_EXPORT void v3270_trace_select_file(GtkWidget *widget) + { + V3270Trace * trace = GTK_V3270_TRACE(widget); + + gchar * filename = + v3270_select_file( + GTK_WIDGET(trace), + _("Save trace to file"), + _("Save"), + GTK_FILE_CHOOSER_ACTION_SAVE, + trace->filename, + N_("Text file"), "*.txt", + NULL + ); + + if(filename) { + g_free(trace->filename); + trace->filename = filename; + v3270_trace_save(widget); + } + + } diff --git a/src/trace/tracewindow.c b/src/trace/tracewindow.c new file mode 100644 index 0000000..54d1795 --- /dev/null +++ b/src/trace/tracewindow.c @@ -0,0 +1,142 @@ +/* + * "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 trace.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) + * + */ + +/** + * SECTION:V3270TraceWindow + * @Short_description: Window containing a trace monitor widget. + * @Title: V3270Trace + * + * The #V3270TraceWindow shows a window with the lib3270 trace output. + * + */ + + #include + + #define ENABLE_NLS + #define GETTEXT_PACKAGE PACKAGE_NAME + + #include + #include + + #include + #include + #include + #include + #include + #include + #include + +#if defined( HAVE_SYSLOG ) + #include +#endif // HAVE_SYSLOG + +/*--[ Implement ]------------------------------------------------------------------------------------*/ + + static void menu_item_new(GtkWidget *menu, const gchar *label, GCallback callback, gpointer data) + { + GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label); + gtk_menu_shell_append(GTK_MENU_SHELL(menu),widget); + g_signal_connect(G_OBJECT(widget), "activate", callback, data); + } + + static void menu_save(G_GNUC_UNUSED GtkWidget *button, GtkWidget *trace) + { + v3270_trace_save(trace); + } + + static void menu_save_as(G_GNUC_UNUSED GtkWidget *button, GtkWidget *trace) + { + v3270_trace_select_file(trace); + } + + static void menu_close(G_GNUC_UNUSED GtkWidget *button, GtkWidget *window) + { + debug("%s",__FUNCTION__); + gtk_widget_destroy(window); + } + + LIB3270_EXPORT GtkWidget * v3270_trace_window_new(GtkWidget *widget, const gchar *header) + { + g_return_val_if_fail(GTK_IS_V3270(widget),NULL); + + GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget * vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0); + GtkWidget * trace = v3270_trace_new(widget); + + gtk_window_set_transient_for(GTK_WINDOW(window),GTK_WINDOW(gtk_widget_get_toplevel(widget))); + gtk_window_set_destroy_with_parent(GTK_WINDOW(window),TRUE); + + // Set window title and default size + { + const gchar * url = lib3270_get_url(v3270_get_session(widget)); + g_autofree gchar * title = NULL; + + if(url) + title = g_strdup_printf("%s - %s - Trace", v3270_get_session_name(widget), url); + else + title = g_strdup_printf("%s - Trace", v3270_get_session_name(widget)); + + gtk_window_set_title(GTK_WINDOW(window), title); + gtk_window_set_default_size(GTK_WINDOW(window),590,430); + } + + // Top menu + { + GtkWidget * menubar = gtk_menu_bar_new(); + GtkWidget * topitem; + GtkWidget * submenu; + + { + // File menu + topitem = gtk_menu_item_new_with_mnemonic(_("_File")); + submenu = gtk_menu_new(); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(topitem), submenu); + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), topitem); + + menu_item_new(submenu,_("_Save"),G_CALLBACK(menu_save),trace); + menu_item_new(submenu,_("Save _As"),G_CALLBACK(menu_save_as),trace); + menu_item_new(submenu,_("_Close"),G_CALLBACK(menu_close),window); + } + + gtk_box_pack_start(GTK_BOX(vbox),menubar,FALSE,TRUE,0); + } + + // Trace window + gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(trace),TRUE,TRUE,0); + + gtk_container_add(GTK_CONTAINER(window),vbox); + gtk_widget_show_all(window); + + if(header) + v3270_trace_append_text(trace,header); + + return window; + } + diff --git a/src/trace/widget.c b/src/trace/widget.c deleted file mode 100644 index a44e97c..0000000 --- a/src/trace/widget.c +++ /dev/null @@ -1,553 +0,0 @@ -/* - * "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 trace.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) - * - */ - -/** - * SECTION:V3270Trace - * @Short_description: A trace monitor widget. - * @Title: V3270Trace - * - * The #V3270Trace shows a text area with the lib3270 trace output. - * - */ - - #include - - #define ENABLE_NLS - #define GETTEXT_PACKAGE PACKAGE_NAME - - #include - #include - - #include - #include - #include - #include - #include - #include - #include - -#if defined( HAVE_SYSLOG ) - #include -#endif // HAVE_SYSLOG - -/*--[ Widget definition ]----------------------------------------------------------------------------*/ - - G_BEGIN_DECLS - - struct _V3270TraceClass - { - GtkBoxClass parent_class; - - }; - - struct _V3270Trace - { - GtkBox parent; - H3270 * hSession; ///< @brief TN3270 Session. - GtkWidget * terminal; ///< @brief V3270 Widget. - GtkScrolledWindow * scroll; - - GtkTextView * view; ///< @brief Text view; - GtkTextBuffer * text; ///< @brief Trace window contents. - GtkEntry * entry; ///< @brief Command line entry. - GtkWidget * buttons; ///< @brief Button bar. - - gchar * filename; ///< @brief Selected file name. - - guint log_handler; ///< @brief GTK Log Handler. - - /// @brief lib3270's saved trace handler. - struct { - void (*handler)(H3270 *session, void *userdata, const char *fmt, va_list args); - void *userdata; - } trace; - - }; - - G_END_DECLS - - G_DEFINE_TYPE(V3270Trace, V3270Trace, GTK_TYPE_BOX); - -/*--[ Implement ]------------------------------------------------------------------------------------*/ - - static void trace_handler(H3270 *hSession, void *userdata, const char *fmt, va_list args) - { - g_autofree gchar *ptr = g_strdup_vprintf(fmt,args); - g_autofree gchar * utftext = g_convert_with_fallback(ptr,-1,"UTF-8",lib3270_get_display_charset(hSession),"?",NULL,NULL,NULL); - - v3270_trace_append_text(GTK_WIDGET(userdata),utftext); - - } - - static void set_session(V3270Trace *widget, H3270 *hSession) - { - // Return if it's the same session. - if(widget->hSession == hSession) - return; - - debug("%s: Session changes %p -> %p", __FUNCTION__, widget->hSession, hSession); - - if(widget->hSession) { - lib3270_set_trace_handler(widget->hSession,widget->trace.handler,widget->trace.userdata); - } - - widget->hSession = hSession; - - if(hSession) { - lib3270_get_trace_handler(hSession,&widget->trace.handler,&widget->trace.userdata); - lib3270_set_trace_handler(hSession,trace_handler,(void *) widget); - } - - } - - static void finalize(GObject *object) - { - debug("V3270Trace::%s",__FUNCTION__); - - V3270Trace *trace = GTK_V3270_TRACE(object); - - if(trace->filename) - { - g_free(trace->filename); - trace->filename = NULL; - } - - if(trace->log_handler) - { - g_log_remove_handler(NULL,trace->log_handler); - trace->log_handler = 0; - } - - set_session(trace,NULL); - g_clear_object(&trace->terminal); - - G_OBJECT_CLASS(V3270Trace_parent_class)->finalize(object); - } - - static void V3270Trace_class_init(G_GNUC_UNUSED V3270TraceClass *klass) - { - G_OBJECT_CLASS(klass)->finalize = finalize; - } - - static void v3270_trace_execute(GtkWidget *widget, const gchar *cmd) - { - if(!*cmd) - return; - - v3270_trace_printf(widget, "%s\n",cmd); - - V3270Trace *trace = GTK_V3270_TRACE(widget); - - if(trace->terminal) - { - int rc = v3270_exec_command(trace->terminal,cmd); - if(rc) - v3270_trace_printf(widget, "rc=%d (%s)\n",rc,strerror(rc)); - } - else - { - v3270_trace_append_text(widget, "Can't execute command without an associated terminal"); - } - - gtk_entry_set_text(trace->entry, ""); - - } - - static void execute_command(GtkEntry *entry, G_GNUC_UNUSED GtkEntryIconPosition icon_pos, G_GNUC_UNUSED GdkEvent *event, GtkWidget *widget) - { - v3270_trace_execute(widget, gtk_entry_get_text(entry)); - } - - static void entry_activated(GtkEntry *entry, GtkWidget *widget) - { - v3270_trace_execute(widget, gtk_entry_get_text(entry)); - } - - static void log_handler(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, GtkWidget *widget) - { - #ifndef LOG_INFO - #define LOG_INFO 0 - #endif // LOG_INFO - - #ifndef LOG_ERR - #define LOG_ERR 0 - #endif // LOG_ERR - - #ifndef LOG_DEBUG - #define LOG_DEBUG 0 - #endif // LOG_DEBUG - - static const struct _logtype - { - GLogLevelFlags log_level; - const gchar * msg; - } logtype[] = - { - { G_LOG_FLAG_RECURSION, "recursion" }, - { G_LOG_FLAG_FATAL, "fatal error" }, - - /* GLib log levels */ - { G_LOG_LEVEL_ERROR, "error" }, - { G_LOG_LEVEL_CRITICAL, "critical error" }, - { G_LOG_LEVEL_WARNING, "warning" }, - { G_LOG_LEVEL_MESSAGE, "message" }, - { G_LOG_LEVEL_INFO, "info" }, - { G_LOG_LEVEL_DEBUG, "debug" }, - }; - - size_t f; - - for(f=0;fbuttons = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); - - gtk_button_box_set_layout(GTK_BUTTON_BOX(widget->buttons), GTK_BUTTONBOX_START); - gtk_box_set_spacing(GTK_BOX(widget->buttons),8); - - gtk_widget_set_valign(widget->buttons,GTK_ALIGN_START); - gtk_box_pack_start(GTK_BOX(widget),widget->buttons,FALSE,FALSE,4); - - } - - // Create text view - { - widget->scroll = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL,NULL)); - gtk_scrolled_window_set_policy(widget->scroll,GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); - gtk_widget_set_vexpand(GTK_WIDGET(widget->scroll),TRUE); - gtk_widget_set_hexpand(GTK_WIDGET(widget->scroll),TRUE); - - gtk_box_pack_start(GTK_BOX(widget),GTK_WIDGET(widget->scroll),TRUE,TRUE,4); - - widget->view = GTK_TEXT_VIEW(gtk_text_view_new()); - -#if GTK_CHECK_VERSION(3,16,0) - gtk_text_view_set_monospace(widget->view,TRUE); -#endif // GTK_CHECK_VERSION - - widget->text = gtk_text_view_get_buffer(widget->view); - gtk_text_view_set_editable(widget->view, TRUE); - - gtk_container_add(GTK_CONTAINER(widget->scroll),GTK_WIDGET(widget->view)); - gtk_widget_set_can_default(GTK_WIDGET(widget->view),FALSE); - - } - - // Create command line - { - widget->entry = GTK_ENTRY(gtk_entry_new()); - - gtk_widget_set_can_default(GTK_WIDGET(widget->entry),TRUE); - gtk_widget_grab_focus(GTK_WIDGET(widget->entry)); - - gtk_entry_set_activates_default(widget->entry,TRUE); - gtk_widget_set_sensitive(GTK_WIDGET(widget->entry),FALSE); - gtk_widget_set_vexpand(GTK_WIDGET(widget->entry),FALSE); - gtk_widget_set_hexpand(GTK_WIDGET(widget->entry),TRUE); - - gtk_entry_set_icon_from_icon_name(widget->entry,GTK_ENTRY_ICON_SECONDARY,"system-run"); - gtk_entry_set_placeholder_text(widget->entry,_("Command to execute")); - - gtk_box_pack_end(GTK_BOX(widget),GTK_WIDGET(widget->entry),FALSE,FALSE,4); - - g_signal_connect(G_OBJECT(widget->entry),"icon-press",G_CALLBACK(execute_command),widget); - g_signal_connect(G_OBJECT(widget->entry),"activate",G_CALLBACK(entry_activated),widget); - - } - - // Grab GTK messages. - widget->log_handler = g_log_set_handler(NULL,G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,(GLogFunc) log_handler, widget); - - } - - - LIB3270_EXPORT GtkWidget * v3270_trace_new(GtkWidget *terminal) - { - g_return_val_if_fail(GTK_IS_V3270(terminal),NULL); - - V3270Trace * widget = GTK_V3270_TRACE(g_object_new(GTK_TYPE_V3270_TRACE, NULL)); - - // Set terminal widget - { - widget->terminal = terminal; - g_object_ref_sink(G_OBJECT(terminal)); - set_session(widget, v3270_get_session(widget->terminal)); - } - - // Create toggle buttons - { - size_t ix; - - static const LIB3270_TOGGLE toggles[] = { LIB3270_TOGGLE_DS_TRACE, LIB3270_TOGGLE_NETWORK_TRACE, LIB3270_TOGGLE_EVENT_TRACE, LIB3270_TOGGLE_SSL_TRACE, LIB3270_TOGGLE_SCREEN_TRACE}; - - for(ix = 0; ix < G_N_ELEMENTS(toggles); ix++) - { - GtkWidget * item = v3270_toggle_button_new(widget->terminal,toggles[ix]); - - gtk_widget_set_can_focus(item,FALSE); - gtk_widget_set_can_default(item,FALSE); - gtk_widget_set_focus_on_click(item,FALSE); - - gtk_box_pack_start(GTK_BOX(widget->buttons),item,FALSE,FALSE,4); - - } - } - - - return GTK_WIDGET(widget); - } - - struct _append_text - { - V3270Trace *widget; - gchar text[1]; - }; - - static gboolean bg_append_text(struct _append_text *cfg) - { - if(!GTK_IS_TEXT_BUFFER(cfg->widget->text)) - return FALSE; - - GtkTextIter itr; - gtk_text_buffer_get_end_iter(cfg->widget->text,&itr); - - if(g_utf8_validate(cfg->text,strlen(cfg->text),NULL)) - { - gtk_text_buffer_insert(cfg->widget->text,&itr,cfg->text,strlen(cfg->text)); - } - else - { - gtk_text_buffer_insert(cfg->widget->text,&itr,"** Invalid UTF8 String **",-1); - } - - // gtk_text_buffer_get_end_iter(cfg->widget->text,&itr); - // gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(cfg->widget->view), &itr, 0.0, FALSE, 0.0, 0.0); - - GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(cfg->widget->scroll); - gtk_adjustment_set_value(vadj,gtk_adjustment_get_upper(vadj)); - gtk_scrolled_window_set_vadjustment(cfg->widget->scroll, vadj); - - return FALSE; - - } - - LIB3270_EXPORT void v3270_trace_append_text(GtkWidget *widget, const gchar *text) - { - g_return_if_fail(GTK_IS_V3270_TRACE(widget)); - - // Enqueue update. - struct _append_text * cfg = g_malloc0(sizeof(struct _append_text)+strlen(text)+1); - cfg->widget = GTK_V3270_TRACE(widget); - strcpy(cfg->text,text); - - g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,(GSourceFunc) bg_append_text, cfg, g_free); - - } - - LIB3270_EXPORT void v3270_trace_vprintf(GtkWidget *widget, const char *fmt, va_list args) - { - g_autofree gchar * text = g_strdup_vprintf(fmt,args); - v3270_trace_append_text(widget,text); - } - - LIB3270_EXPORT void v3270_trace_printf(GtkWidget *widget, const char *fmt, ... ) - { - va_list arg_ptr; - va_start(arg_ptr, fmt); - v3270_trace_vprintf(widget,fmt,arg_ptr); - va_end(arg_ptr); - } - - static void menu_item_new(GtkWidget *menu, const gchar *label, GCallback callback, gpointer data) - { - GtkWidget *widget = gtk_menu_item_new_with_mnemonic(label); - gtk_menu_shell_append(GTK_MENU_SHELL(menu),widget); - g_signal_connect(G_OBJECT(widget), "activate", callback, data); - } - - static void menu_save(G_GNUC_UNUSED GtkWidget *button, GtkWidget *trace) - { - v3270_trace_save(trace); - } - - static void menu_save_as(G_GNUC_UNUSED GtkWidget *button, GtkWidget *trace) - { - v3270_trace_select_file(trace); - } - - static void menu_close(G_GNUC_UNUSED GtkWidget *button, GtkWidget *window) - { - debug("%s",__FUNCTION__); - gtk_widget_destroy(window); - } - - LIB3270_EXPORT GtkWidget * v3270_trace_window_new(GtkWidget *widget, const gchar *header) - { - g_return_val_if_fail(GTK_IS_V3270(widget),NULL); - - GtkWidget * window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - GtkWidget * vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0); - GtkWidget * trace = v3270_trace_new(widget); - - // Set window title and default size - { - const gchar * url = lib3270_get_url(v3270_get_session(widget)); - g_autofree gchar * title = NULL; - - if(url) - title = g_strdup_printf("%s - %s - Trace", v3270_get_session_name(widget), url); - else - title = g_strdup_printf("%s - Trace", v3270_get_session_name(widget)); - - gtk_window_set_title(GTK_WINDOW(window), title); - gtk_window_set_default_size(GTK_WINDOW(window),590,430); - } - - // Top menu - { - GtkWidget * menubar = gtk_menu_bar_new(); - GtkWidget * topitem = gtk_menu_item_new_with_mnemonic(_("_File")); - GtkWidget * submenu = gtk_menu_new(); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(topitem), submenu); - gtk_menu_shell_append(GTK_MENU_SHELL(menubar), topitem); - - menu_item_new(submenu,_("_Save"),G_CALLBACK(menu_save),trace); - menu_item_new(submenu,_("Save _As"),G_CALLBACK(menu_save_as),trace); - menu_item_new(submenu,_("_Close"),G_CALLBACK(menu_close),window); - - gtk_box_pack_start(GTK_BOX(vbox),menubar,FALSE,TRUE,0); - } - - // Trace window - gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(trace),TRUE,TRUE,0); - - gtk_container_add(GTK_CONTAINER(window),vbox); - gtk_widget_show_all(window); - - if(header) - v3270_trace_append_text(trace,header); - - return window; - } - - LIB3270_EXPORT void v3270_trace_save(GtkWidget *widget) - { - V3270Trace * trace = GTK_V3270_TRACE(widget); - - if(trace && trace->filename) - { - GError * error = NULL; - gchar * text; - GtkTextIter start; - GtkTextIter end; - - gtk_text_buffer_get_start_iter(trace->text,&start); - gtk_text_buffer_get_end_iter(trace->text,&end); - text = gtk_text_buffer_get_text(trace->text,&start,&end,FALSE); - - g_file_set_contents(trace->filename,text,-1,&error); - - g_free(text); - - 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" ), - trace->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); - - gtk_dialog_run(GTK_DIALOG(popup)); - gtk_widget_destroy(popup); - - } - - } - - } - - LIB3270_EXPORT void v3270_trace_select_file(GtkWidget *widget) - { - V3270Trace * trace = GTK_V3270_TRACE(widget); - - gchar * filename = - v3270_select_file( - GTK_WIDGET(trace), - _("Save trace to file"), - _("Save"), - GTK_FILE_CHOOSER_ACTION_SAVE, - trace->filename, - N_("Text file"), "*.txt", - NULL - ); - - if(filename) { - g_free(trace->filename); - trace->filename = filename; - v3270_trace_save(widget); - } - - } - diff --git a/v3270.cbp b/v3270.cbp index 420f4f5..336ce2b 100644 --- a/v3270.cbp +++ b/v3270.cbp @@ -260,7 +260,10 @@ - + + + -- libgit2 0.21.2