Commit eddb289431bef11b13c9d8382eb2c159ee8aa5ba

Authored by Perry Werneck
1 parent f5e3345e
Exists in master and in 1 other branch develop

Adding simple trace window.

Showing 1 changed file with 485 additions and 0 deletions   Show diff stats
src/trace/trace.c 0 → 100644
... ... @@ -0,0 +1,485 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como trace.c e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 + #include <gtk/gtk.h>
  31 +
  32 + #define ENABLE_NLS
  33 + #define GETTEXT_PACKAGE PACKAGE_NAME
  34 +
  35 + #include <libintl.h>
  36 + #include <glib/gi18n.h>
  37 +
  38 + #include <v3270/trace.h>
  39 +
  40 +#if defined( HAVE_SYSLOG )
  41 + #include <syslog.h>
  42 +#endif // HAVE_SYSLOG
  43 +
  44 +/*--[ Widget definition ]----------------------------------------------------------------------------*/
  45 +
  46 + G_BEGIN_DECLS
  47 +
  48 + struct _v3270_traceClass
  49 + {
  50 + GtkWindowClass parent_class;
  51 + };
  52 +
  53 + struct _v3270_trace
  54 + {
  55 + GtkWindow parent;
  56 + GtkAdjustment * scroll;
  57 + GtkTextBuffer * text;
  58 + GtkWidget * entry;
  59 + GtkWidget * button;
  60 + gchar **line;
  61 + guint log_handler;
  62 + gboolean * enabled;
  63 + gboolean destroy_on_close;
  64 + };
  65 +
  66 + const GtkWindowClass * v3270_trace_get_parent_class(void);
  67 +
  68 + G_END_DECLS
  69 +
  70 + G_DEFINE_TYPE(v3270_trace, v3270_trace, GTK_TYPE_WINDOW);
  71 +
  72 +/*--[ Implement ]------------------------------------------------------------------------------------*/
  73 +
  74 + const GtkWindowClass * v3270_trace_get_parent_class(void)
  75 + {
  76 + return GTK_WINDOW_CLASS(v3270_trace_parent_class);
  77 + }
  78 +
  79 + static void activate_default(GtkWindow *window)
  80 + {
  81 + v3270_trace * hwnd = V3270_TRACE(window);
  82 +
  83 + if(hwnd->enabled)
  84 + {
  85 + if(*hwnd->line)
  86 + g_free(*hwnd->line);
  87 +
  88 + *hwnd->line = g_strdup(gtk_entry_get_text(GTK_ENTRY(hwnd->entry)));
  89 +
  90 + gtk_widget_set_sensitive(hwnd->entry,FALSE);
  91 + gtk_widget_set_sensitive(hwnd->button,FALSE);
  92 +
  93 + *hwnd->enabled = FALSE;
  94 + }
  95 +
  96 + }
  97 +
  98 +#if GTK_CHECK_VERSION(3,0,0)
  99 +static void destroy(GtkWidget *widget)
  100 +#else
  101 +static void destroy(GtkObject *widget)
  102 +#endif
  103 + {
  104 + v3270_trace * hwnd = V3270_TRACE(widget);
  105 +
  106 + if(hwnd->log_handler)
  107 + {
  108 + g_log_remove_handler(NULL,hwnd->log_handler);
  109 + hwnd->log_handler = 0;
  110 + }
  111 +
  112 + if(hwnd->line)
  113 + *hwnd->line = NULL;
  114 +
  115 + if(hwnd->enabled)
  116 + *hwnd->enabled = FALSE;
  117 +
  118 + }
  119 +
  120 + static gboolean delete_event(GtkWidget *widget, G_GNUC_UNUSED GdkEventAny *event)
  121 + {
  122 + v3270_trace * hwnd = V3270_TRACE(widget);
  123 +
  124 + if(hwnd->line)
  125 + *hwnd->line = NULL;
  126 +
  127 + if(hwnd->enabled)
  128 + *hwnd->enabled = FALSE;
  129 +
  130 + if(hwnd->destroy_on_close)
  131 + return FALSE;
  132 +
  133 + gtk_widget_hide(widget);
  134 + return TRUE;
  135 + }
  136 +
  137 + static void v3270_trace_class_init(v3270_traceClass *klass)
  138 + {
  139 + GtkWindowClass * window_class = GTK_WINDOW_CLASS(klass);
  140 + GtkWidgetClass * widget_class = GTK_WIDGET_CLASS(klass);
  141 +
  142 + window_class->activate_default = activate_default;
  143 + widget_class->delete_event = delete_event;
  144 +
  145 +#if GTK_CHECK_VERSION(3,0,0)
  146 + {
  147 + widget_class->destroy = destroy;
  148 + }
  149 +#else
  150 + {
  151 + GtkObjectClass *object_class = (GtkObjectClass*) klass;
  152 + object_class->destroy = destroy;
  153 + }
  154 +#endif // GTK3
  155 +
  156 + }
  157 +
  158 + static void activate(G_GNUC_UNUSED GtkButton *button, GtkWindow *window)
  159 + {
  160 + activate_default(window);
  161 + }
  162 +
  163 + static void menu_save(G_GNUC_UNUSED GtkWidget *button, v3270_trace *window)
  164 + {
  165 + GtkWindow * toplevel = GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(window)));
  166 + GtkWidget * dialog;
  167 +
  168 + dialog = gtk_file_chooser_dialog_new( _( "Save trace file" ),
  169 + toplevel,
  170 + GTK_FILE_CHOOSER_ACTION_SAVE,
  171 + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  172 + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
  173 + NULL );
  174 +
  175 + gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), TRUE);
  176 +
  177 + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),g_get_user_special_dir(G_USER_DIRECTORY_DOCUMENTS));
  178 +
  179 + if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT)
  180 + {
  181 + gchar *filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
  182 + if(filename)
  183 + {
  184 + GError * error = NULL;
  185 + gchar * text;
  186 + GtkTextIter start;
  187 + GtkTextIter end;
  188 +
  189 + gtk_text_buffer_get_start_iter(window->text,&start);
  190 + gtk_text_buffer_get_end_iter(window->text,&end);
  191 + text = gtk_text_buffer_get_text(window->text,&start,&end,FALSE);
  192 +
  193 + g_file_set_contents(filename,text,-1,&error);
  194 +
  195 + g_free(text);
  196 +
  197 + if(error)
  198 + {
  199 + GtkWidget *popup = gtk_message_dialog_new_with_markup(GTK_WINDOW(dialog),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,GTK_MESSAGE_ERROR,GTK_BUTTONS_CLOSE,_( "Can't save %s" ),filename);
  200 +
  201 + gtk_window_set_title(GTK_WINDOW(popup),_("Can't save file"));
  202 +
  203 + gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(popup),"%s",error->message);
  204 + g_error_free(error);
  205 +
  206 + gtk_dialog_run(GTK_DIALOG(popup));
  207 + gtk_widget_destroy(popup);
  208 +
  209 + }
  210 +
  211 + g_free(filename);
  212 + }
  213 + }
  214 +
  215 + gtk_widget_destroy(dialog);
  216 +
  217 + }
  218 +
  219 + static void menu_close(G_GNUC_UNUSED GtkWidget *button, GtkWidget *window)
  220 + {
  221 + gtk_widget_destroy(window);
  222 + }
  223 +
  224 + struct submenu
  225 + {
  226 + const gchar * stock_id;
  227 + GCallback action;
  228 + };
  229 +
  230 + static void build_menu(GtkWidget *menubar, v3270_trace *window, const gchar *name, const struct submenu *item, size_t sz)
  231 + {
  232 + size_t f;
  233 + GtkWidget * menu = gtk_menu_new();
  234 + GtkWidget * topitem = gtk_image_menu_item_new_from_stock( name, NULL );
  235 +
  236 + gtk_menu_item_set_submenu(GTK_MENU_ITEM(topitem), menu);
  237 +
  238 + for(f=0;f<sz;f++)
  239 + {
  240 + GtkWidget *widget = gtk_image_menu_item_new_from_stock( item[f].stock_id, NULL );
  241 + gtk_menu_shell_append(GTK_MENU_SHELL(menu),widget);
  242 + g_signal_connect(G_OBJECT(widget), "activate",item[f].action,window);
  243 + }
  244 +
  245 + gtk_menu_shell_append(GTK_MENU_SHELL(menubar), topitem);
  246 + }
  247 +
  248 + static void glog(const gchar *log_domain,GLogLevelFlags log_level,const gchar *message,GtkWidget *window)
  249 + {
  250 + #ifndef LOG_INFO
  251 + #define LOG_INFO 0
  252 + #endif // LOG_INFO
  253 +
  254 + #ifndef LOG_ERR
  255 + #define LOG_ERR 0
  256 + #endif // LOG_ERR
  257 +
  258 + #ifndef LOG_DEBUG
  259 + #define LOG_DEBUG 0
  260 + #endif // LOG_DEBUG
  261 +
  262 + static const struct _logtype
  263 + {
  264 + GLogLevelFlags log_level;
  265 + int priority;
  266 + const gchar * msg;
  267 + } logtype[] =
  268 + {
  269 + { G_LOG_FLAG_RECURSION, LOG_INFO, "recursion" },
  270 + { G_LOG_FLAG_FATAL, LOG_ERR, "fatal error" },
  271 +
  272 + /* GLib log levels */
  273 + { G_LOG_LEVEL_ERROR, LOG_ERR, "error" },
  274 + { G_LOG_LEVEL_CRITICAL, LOG_ERR, "critical error" },
  275 + { G_LOG_LEVEL_WARNING, LOG_ERR, "warning" },
  276 + { G_LOG_LEVEL_MESSAGE, LOG_ERR, "message" },
  277 + { G_LOG_LEVEL_INFO, LOG_INFO, "info" },
  278 + { G_LOG_LEVEL_DEBUG, LOG_DEBUG, "debug" },
  279 + };
  280 +
  281 + size_t f;
  282 +
  283 + for(f=0;f<G_N_ELEMENTS(logtype);f++)
  284 + {
  285 + if(logtype[f].log_level == log_level)
  286 + {
  287 + gchar *ptr;
  288 + gchar *text = g_strdup_printf("%s: %s %s",logtype[f].msg,log_domain ? log_domain : "",message);
  289 + for(ptr = text;*ptr;ptr++)
  290 + {
  291 + if(*ptr < ' ')
  292 + *ptr = ' ';
  293 + }
  294 +
  295 + v3270_trace_printf(window,"%s\n",text);
  296 +
  297 +#ifdef HAVE_SYSLOG
  298 + syslog(logtype[f].priority,"%s",text);
  299 +#endif // HAVE_SYSLOG
  300 + g_free(text);
  301 + return;
  302 + }
  303 + }
  304 +
  305 + v3270_trace_printf(window,"%s %s\n",log_domain ? log_domain : "", message);
  306 +
  307 +#ifdef HAVE_SYSLOG
  308 + syslog(LOG_INFO,"%s %s",log_domain ? log_domain : "", message);
  309 +#endif // HAVE_SYSLOG
  310 +
  311 + }
  312 +
  313 + static void v3270_trace_init(v3270_trace *window)
  314 + {
  315 + GtkWidget * widget;
  316 + GtkWidget * view;
  317 +#if GTK_CHECK_VERSION(3,0,0)
  318 + GtkWidget * vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
  319 +#else
  320 + GtkWidget * vbox = gtk_vbox_new(FALSE,0);
  321 +#endif // GTK_CHECK_VERSION
  322 + gchar * fontname = "Monospace";
  323 + PangoFontDescription * fontdesc = pango_font_description_from_string(fontname);
  324 +
  325 + g_free(fontname);
  326 +
  327 + // Top menu
  328 + {
  329 +
  330 + static const struct submenu filemenu[] =
  331 + {
  332 + { GTK_STOCK_SAVE_AS, G_CALLBACK(menu_save) },
  333 + { GTK_STOCK_QUIT, G_CALLBACK(menu_close) },
  334 +
  335 + };
  336 +
  337 + widget = gtk_menu_bar_new();
  338 +
  339 + build_menu(widget, window, GTK_STOCK_FILE, filemenu, G_N_ELEMENTS(filemenu));
  340 +
  341 + gtk_box_pack_start(GTK_BOX(vbox),widget,FALSE,TRUE,0);
  342 + }
  343 +
  344 + // Trace container
  345 + widget = gtk_scrolled_window_new(NULL,NULL);
  346 + window->scroll = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(widget));
  347 + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(widget),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
  348 + view = gtk_text_view_new();
  349 +
  350 +#if GTK_CHECK_VERSION(3,0,0)
  351 + gtk_widget_override_font(GTK_WIDGET(view), fontdesc);
  352 +#else
  353 + gtk_widget_modify_font(GTK_WIDGET(view), fontdesc);
  354 +#endif // GTK_CHECK_VERSION
  355 +
  356 + window->text = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
  357 + gtk_text_view_set_editable(GTK_TEXT_VIEW(view), TRUE);
  358 +
  359 +#if GTK_CHECK_VERSION(3,8,0)
  360 + gtk_container_add(GTK_CONTAINER(widget),view);
  361 +#else
  362 + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(widget),view);
  363 +#endif // GTK_CHECK_VERSION
  364 + gtk_box_pack_start(GTK_BOX(vbox),widget,TRUE,TRUE,0);
  365 +
  366 + // Edit box
  367 +#if GTK_CHECK_VERSION(3,0,0)
  368 + widget = gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
  369 +#else
  370 + widget = gtk_hbox_new(FALSE,0);
  371 +#endif // GTK_CHECK_VERSION
  372 + gtk_box_pack_start(GTK_BOX(widget),gtk_label_new( _( "Command:" )),FALSE,TRUE,4);
  373 + window->entry = gtk_entry_new();
  374 + gtk_box_pack_start(GTK_BOX(widget),window->entry,TRUE,TRUE,4);
  375 + gtk_widget_set_sensitive(window->entry,FALSE);
  376 + g_signal_connect(G_OBJECT(window->entry),"activate",G_CALLBACK(activate),window);
  377 +
  378 + window->button = gtk_button_new_from_stock(GTK_STOCK_OK);
  379 + gtk_box_pack_end(GTK_BOX(widget),window->button,FALSE,FALSE,4);
  380 + gtk_widget_set_sensitive(window->button,FALSE);
  381 + gtk_widget_set_focus_on_click(GTK_BUTTON(window->button),FALSE);
  382 +
  383 + g_signal_connect(G_OBJECT(window->button),"clicked",G_CALLBACK(activate),window);
  384 +
  385 + gtk_box_pack_start(GTK_BOX(vbox),widget,FALSE,TRUE,0);
  386 +
  387 + gtk_widget_show_all(vbox);
  388 +
  389 + gtk_container_add(GTK_CONTAINER(window),vbox);
  390 +
  391 + pango_font_description_free(fontdesc);
  392 +
  393 + window->log_handler = g_log_set_handler(NULL,G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,(GLogFunc) glog,window);
  394 +
  395 + }
  396 +
  397 + GtkWidget * v3270_trace_new(H3270 *hSession)
  398 + {
  399 + return g_object_new(V3270_TYPE_TRACE, NULL);
  400 + }
  401 +
  402 + LIB3270_EXPORT GtkWidget * v3270_trace_new_from_session(H3270 *hSession) {
  403 + GtkWidget * widget = g_object_new(V3270_TYPE_TRACE, NULL);
  404 + void * terminal = lib3270_get_user_data(hSession);
  405 +
  406 + gtk_window_set_default_size(GTK_WINDOW(widget),590,430);
  407 +
  408 + if(terminal && GTK_IS_V3270(terminal))
  409 + {
  410 + GtkWidget * toplevel = gtk_widget_get_toplevel(GTK_WIDGET(terminal));
  411 + gtk_window_set_attached_to(GTK_WINDOW(widget),toplevel);
  412 +
  413 + }
  414 +
  415 + return widget;
  416 + }
  417 +
  418 +
  419 + void v3270_trace_vprintf(GtkWidget *widget, const char *fmt, va_list args)
  420 + {
  421 + GtkTextIter itr;
  422 + gchar * msg;
  423 + v3270_trace * hwnd = V3270_TRACE(widget);
  424 +
  425 + gtk_text_buffer_get_end_iter(hwnd->text,&itr);
  426 +
  427 + msg = g_strdup_vprintf(fmt,args);
  428 +
  429 + if(g_utf8_validate(msg,strlen(msg),NULL))
  430 + {
  431 + gtk_text_buffer_insert(hwnd->text,&itr,msg,strlen(msg));
  432 + }
  433 + else
  434 + {
  435 + gtk_text_buffer_insert(hwnd->text,&itr,"** Invalid UTF8 String **",-1);
  436 + }
  437 + g_free(msg);
  438 +
  439 + gtk_text_buffer_get_end_iter(hwnd->text,&itr);
  440 +
  441 +#if GTK_CHECK_VERSION(2,14,0)
  442 + gtk_adjustment_set_value(hwnd->scroll,gtk_adjustment_get_upper(hwnd->scroll));
  443 +#else
  444 + gtk_adjustment_set_value(hwnd->scroll,(GTK_ADJUSTMENT(hwnd->scroll))->upper);
  445 +#endif //
  446 +
  447 + }
  448 +
  449 + void v3270_trace_printf(GtkWidget *widget, const char *fmt, ... )
  450 + {
  451 + va_list arg_ptr;
  452 + va_start(arg_ptr, fmt);
  453 + v3270_trace_vprintf(widget,fmt,arg_ptr);
  454 + va_end(arg_ptr);
  455 + }
  456 +
  457 + LIB3270_EXPORT gchar * v3270_trace_get_command(GtkWidget *widget)
  458 + {
  459 + v3270_trace * hwnd = V3270_TRACE(widget);
  460 + gchar * line = NULL;
  461 + gboolean enabled = TRUE;
  462 +
  463 + hwnd->line = &line;
  464 + hwnd->enabled = &enabled;
  465 +
  466 + gtk_window_present(GTK_WINDOW(widget));
  467 + gtk_widget_set_sensitive(hwnd->entry,TRUE);
  468 + gtk_widget_set_sensitive(hwnd->button,TRUE);
  469 + gtk_widget_grab_focus(hwnd->entry);
  470 +
  471 + while(enabled)
  472 + {
  473 + gtk_main_iteration();
  474 + }
  475 +
  476 + hwnd->line = NULL;
  477 + hwnd->enabled = NULL;
  478 +
  479 + return line;
  480 + }
  481 +
  482 + LIB3270_EXPORT void v3270_trace_set_destroy_on_close(GtkWidget *widget,gboolean on)
  483 + {
  484 + V3270_TRACE(widget)->destroy_on_close = on;
  485 + }
... ...