/* * "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 #if defined( HAVE_SYSLOG ) #include #endif // HAVE_SYSLOG /*--[ Widget definition ]----------------------------------------------------------------------------*/ G_BEGIN_DECLS struct _V3270TraceClass { GtkGridClass parent_class; }; struct _V3270Trace { GtkGrid parent; H3270 * hSession; /// @brief TN3270 Session. GtkWidget * terminal; /// @brief V3270 Widget. GtkTextBuffer * text; /// @brief Trace window contents. GtkEntry * entry; /// @brief Command line entry. /// @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_GRID); /*--[ 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; 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); 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 V3270Trace_init(V3270Trace *widget) { gtk_grid_set_row_spacing(GTK_GRID(widget),6); gtk_grid_set_column_spacing(GTK_GRID(widget),12); // Create text view { GtkWidget *scrolled = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); gtk_widget_set_vexpand(scrolled,TRUE); gtk_widget_set_hexpand(scrolled,TRUE); gtk_grid_attach(GTK_GRID(widget),scrolled,0,0,10,1); GtkWidget *view = gtk_text_view_new(); gtk_text_view_set_monospace(GTK_TEXT_VIEW(view),TRUE); widget->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)); gtk_text_view_set_editable(GTK_TEXT_VIEW(view), TRUE); gtk_container_add(GTK_CONTAINER(scrolled),view); gtk_widget_set_can_default(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_grid_attach(GTK_GRID(widget),GTK_WIDGET(widget->entry),0,1,10,1); 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); } } LIB3270_EXPORT void v3270_trace_set_terminal(GtkWidget *widget, GtkWidget *terminal) { V3270Trace * trace = GTK_V3270_TRACE(widget); if(trace->terminal == terminal) return; g_clear_object(&trace->terminal); if(terminal) { trace->terminal = terminal; g_object_ref_sink(G_OBJECT(terminal)); } set_session(trace, v3270_get_session(trace->terminal)); gtk_widget_set_sensitive(GTK_WIDGET(trace->entry),trace->terminal != NULL); } 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)); v3270_trace_set_terminal(GTK_WIDGET(widget),terminal); return GTK_WIDGET(widget); } struct _append_text { V3270Trace *widget; gchar text[1]; }; static void bg_append_text(struct _append_text *cfg) { 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(hwnd->text,&itr); // gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW(hwnd->view), &itr, 0.0, FALSE, 0.0, 0.0); //GtkAdjustment *vadj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(hwnd->scroll)); //gtk_adjustment_set_value(vadj,gtk_adjustment_get_upper(vadj)); //gtk_scrolled_window_set_vadjustment(GTK_SCROLLED_WINDOW(hwnd->scroll), vadj); } LIB3270_EXPORT void v3270_trace_append_text(GtkWidget *widget, const gchar *text) { debug("widget=%p text=\"%s\"",widget,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); gdk_threads_add_idle_full(G_PRIORITY_LOW,(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_as(G_GNUC_UNUSED GtkWidget *button, V3270Trace *trace) { debug("%s",__FUNCTION__); } static void menu_close(G_GNUC_UNUSED GtkWidget *button, GtkWidget *window) { debug("%s",__FUNCTION__); gtk_widget_destroy(window); } LIB3270_EXPORT GtkWidget * v3270_new_trace_window(GtkWidget *widget) { 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); V3270Trace * trace = v3270_trace_new(widget); gtk_window_set_default_size(GTK_WINDOW(widget),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 _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); return window; }