Commit eddb289431bef11b13c9d8382eb2c159ee8aa5ba
1 parent
f5e3345e
Exists in
master
and in
1 other branch
Adding simple trace window.
Showing
1 changed file
with
485 additions
and
0 deletions
Show diff stats
... | ... | @@ -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 | + } | ... | ... |