5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #include <epan/epan.h>
36 #include <epan/filesystem.h>
37 #include <epan/epan_dissect.h>
38 #include <epan/expert.h>
39 #include <epan/prefs.h>
43 #include "../capture_opts.h"
44 #include "../capture_ui_utils.h"
46 #include "../capture.h"
49 #include "gtk/recent.h"
51 #include "gtk/main_statusbar.h"
52 #include "gtk/main_statusbar_private.h"
53 #include "gtk/gui_utils.h"
54 #include "gtk/gtkglobals.h"
55 #include "gtk/expert_comp_dlg.h"
56 #include "gtk/profile_dlg.h"
58 #include "../image/expert_error.xpm"
59 #include "../image/expert_warn.xpm"
60 #include "../image/expert_note.xpm"
61 #include "../image/expert_chat.xpm"
62 #include "../image/expert_none.xpm"
65 * The order below defines the priority of info bar contexts.
77 #define DEF_READY_MESSAGE " Ready to load or capture"
79 #define DEF_READY_MESSAGE " Ready to load file"
83 GtkWidget *status_pane_left, *status_pane_right;
84 GtkWidget *info_bar, *packets_bar, *profile_bar, *profile_bar_event;
85 GtkWidget *expert_info_error, *expert_info_warn, *expert_info_note;
86 GtkWidget *expert_info_chat, *expert_info_none;
88 static guint main_ctx, file_ctx, help_ctx, filter_ctx, packets_ctx, profile_ctx;
89 static guint status_levels[NUM_STATUS_LEVELS];
90 static gchar *packets_str = NULL;
91 static gchar *profile_str = NULL;
94 static void info_bar_new(void);
95 static void packets_bar_new(void);
96 static void profile_bar_new(void);
97 static void status_expert_new(void);
102 * Push a message referring to file access onto the statusbar.
105 statusbar_push_file_msg(const gchar *msg)
109 /*g_warning("statusbar_push: %s", msg);*/
110 for (i = STATUS_LEVEL_FILE + 1; i < NUM_STATUS_LEVELS; i++) {
111 if (status_levels[i])
114 status_levels[STATUS_LEVEL_FILE]++;
115 gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
119 * Pop a message referring to file access off the statusbar.
122 statusbar_pop_file_msg(void)
124 /*g_warning("statusbar_pop");*/
125 if (status_levels[STATUS_LEVEL_FILE] > 0) {
126 status_levels[STATUS_LEVEL_FILE]--;
128 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
132 * Push a message referring to the currently-selected field onto the statusbar.
135 statusbar_push_field_msg(const gchar *msg)
139 for (i = STATUS_LEVEL_HELP + 1; i < NUM_STATUS_LEVELS; i++) {
140 if (status_levels[i])
143 status_levels[STATUS_LEVEL_HELP]++;
145 gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
149 * Pop a message referring to the currently-selected field off the statusbar.
152 statusbar_pop_field_msg(void)
154 if (status_levels[STATUS_LEVEL_HELP] > 0) {
155 status_levels[STATUS_LEVEL_HELP]--;
157 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
161 * Push a message referring to the current filter onto the statusbar.
164 statusbar_push_filter_msg(const gchar *msg)
168 for (i = STATUS_LEVEL_FILTER + 1; i < NUM_STATUS_LEVELS; i++) {
169 if (status_levels[i])
172 status_levels[STATUS_LEVEL_FILTER]++;
174 gtk_statusbar_push(GTK_STATUSBAR(info_bar), filter_ctx, msg);
178 * Pop a message referring to the current filter off the statusbar.
181 statusbar_pop_filter_msg(void)
183 if (status_levels[STATUS_LEVEL_FILTER] > 0) {
184 status_levels[STATUS_LEVEL_FILTER]--;
186 gtk_statusbar_pop(GTK_STATUSBAR(info_bar), filter_ctx);
193 GtkWidget *status_hbox;
196 status_hbox = gtk_hbox_new(FALSE, 1);
197 gtk_container_set_border_width(GTK_CONTAINER(status_hbox), 0);
199 /* info (main) statusbar */
202 /* packets statusbar */
205 /* profile statusbar */
208 /* expert info indicator */
211 /* Pane for the statusbar */
212 status_pane_left = gtk_hpaned_new();
213 gtk_widget_show(status_pane_left);
214 status_pane_right = gtk_hpaned_new();
215 gtk_widget_show(status_pane_right);
221 statusbar_load_window_geometry(void)
223 if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_left)
224 gtk_paned_set_position(GTK_PANED(status_pane_left), recent.gui_geometry_status_pane_left);
225 if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_right)
226 gtk_paned_set_position(GTK_PANED(status_pane_right), recent.gui_geometry_status_pane_right);
230 statusbar_save_window_geometry(void)
232 recent.gui_geometry_status_pane_left = gtk_paned_get_position(GTK_PANED(status_pane_left));
233 recent.gui_geometry_status_pane_right = gtk_paned_get_position(GTK_PANED(status_pane_right));
238 * Helper for statusbar_widgets_emptying()
241 foreach_remove_a_child(GtkWidget *widget, gpointer data) {
242 gtk_container_remove(GTK_CONTAINER(data), widget);
246 statusbar_widgets_emptying(GtkWidget *statusbar)
248 gtk_widget_ref(info_bar);
249 gtk_widget_ref(packets_bar);
250 gtk_widget_ref(profile_bar);
251 gtk_widget_ref(profile_bar_event);
252 gtk_widget_ref(status_pane_left);
253 gtk_widget_ref(status_pane_right);
254 gtk_widget_ref(expert_info_error);
255 gtk_widget_ref(expert_info_warn);
256 gtk_widget_ref(expert_info_note);
257 gtk_widget_ref(expert_info_chat);
258 gtk_widget_ref(expert_info_none);
260 /* empty all containers participating */
261 gtk_container_foreach(GTK_CONTAINER(statusbar), foreach_remove_a_child, statusbar);
262 gtk_container_foreach(GTK_CONTAINER(status_pane_left), foreach_remove_a_child, status_pane_left);
263 gtk_container_foreach(GTK_CONTAINER(status_pane_right), foreach_remove_a_child, status_pane_right);
267 statusbar_widgets_pack(GtkWidget *statusbar)
269 gtk_box_pack_start(GTK_BOX(statusbar), expert_info_error, FALSE, FALSE, 0);
270 gtk_box_pack_start(GTK_BOX(statusbar), expert_info_warn, FALSE, FALSE, 0);
271 gtk_box_pack_start(GTK_BOX(statusbar), expert_info_note, FALSE, FALSE, 0);
272 gtk_box_pack_start(GTK_BOX(statusbar), expert_info_chat, FALSE, FALSE, 0);
273 gtk_box_pack_start(GTK_BOX(statusbar), expert_info_none, FALSE, FALSE, 0);
274 gtk_box_pack_start(GTK_BOX(statusbar), status_pane_left, TRUE, TRUE, 0);
275 gtk_paned_pack1(GTK_PANED(status_pane_left), info_bar, FALSE, FALSE);
276 gtk_paned_pack2(GTK_PANED(status_pane_left), status_pane_right, TRUE, FALSE);
277 gtk_paned_pack1(GTK_PANED(status_pane_right), packets_bar, TRUE, FALSE);
278 gtk_paned_pack2(GTK_PANED(status_pane_right), profile_bar_event, FALSE, FALSE);
282 statusbar_widgets_show_or_hide(GtkWidget *statusbar)
285 * Show the status hbox if either:
287 * 1) we're showing the filter toolbar and we want it in the status
292 * 2) we're showing the status bar.
294 if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
295 recent.statusbar_show) {
296 gtk_widget_show(statusbar);
298 gtk_widget_hide(statusbar);
301 if (recent.statusbar_show) {
302 gtk_widget_show(status_pane_left);
304 gtk_widget_hide(status_pane_left);
314 /* tip: tooltips don't work on statusbars! */
315 info_bar = gtk_statusbar_new();
316 main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
317 file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
318 help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
319 filter_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "filter");
320 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
321 gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
323 for (i = 0; i < NUM_STATUS_LEVELS; i++) {
324 status_levels[i] = 0;
327 gtk_widget_show(info_bar);
331 packets_bar_new(void)
333 /* tip: tooltips don't work on statusbars! */
334 packets_bar = gtk_statusbar_new();
335 packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
336 packets_bar_update();
337 gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(packets_bar), FALSE);
339 gtk_widget_show(packets_bar);
343 profile_bar_new(void)
345 GtkTooltips *tooltips;
347 tooltips = gtk_tooltips_new();
349 profile_bar_event = gtk_event_box_new();
350 profile_bar = gtk_statusbar_new();
351 gtk_container_add(GTK_CONTAINER(profile_bar_event), profile_bar);
352 g_signal_connect(profile_bar_event, "button_press_event", G_CALLBACK(profile_show_popup_cb), NULL);
353 profile_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(profile_bar), "profile");
354 gtk_tooltips_set_tip (tooltips, profile_bar_event,
355 "Click to change configuration profile", NULL);
356 profile_bar_update();
358 gtk_widget_show(profile_bar);
359 gtk_widget_show(profile_bar_event);
364 * update the packets statusbar to the current values
367 packets_bar_update(void)
371 /* remove old status */
374 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
377 /* do we have any packets? */
379 if(cfile.drops_known) {
380 packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u Dropped: %u",
381 cfile.count, cfile.displayed_count, cfile.marked_count, cfile.drops);
383 packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u",
384 cfile.count, cfile.displayed_count, cfile.marked_count);
387 packets_str = g_strdup(" No Packets");
389 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
394 * update the packets statusbar to the current values
397 profile_bar_update(void)
400 /* remove old status */
403 gtk_statusbar_pop(GTK_STATUSBAR(profile_bar), profile_ctx);
406 profile_str = g_strdup_printf (" Profile: %s", get_profile_name ());
408 gtk_statusbar_push(GTK_STATUSBAR(profile_bar), profile_ctx, profile_str);
414 status_expert_new(void)
416 GtkWidget *expert_image;
417 GtkTooltips *tooltips;
419 tooltips = gtk_tooltips_new();
421 expert_image = xpm_to_widget_from_parent(top_level, expert_error_xpm);
422 gtk_tooltips_set_tip(tooltips, expert_image, "ERROR is the highest expert info level", NULL);
423 gtk_widget_show(expert_image);
424 expert_info_error = gtk_event_box_new();
425 gtk_container_add(GTK_CONTAINER(expert_info_error), expert_image);
426 g_signal_connect(expert_info_error, "button_press_event", G_CALLBACK(expert_comp_dlg_cb), NULL);
428 expert_image = xpm_to_widget_from_parent(top_level, expert_warn_xpm);
429 gtk_tooltips_set_tip(tooltips, expert_image, "WARNING is the highest expert info level", NULL);
430 gtk_widget_show(expert_image);
431 expert_info_warn = gtk_event_box_new();
432 gtk_container_add(GTK_CONTAINER(expert_info_warn), expert_image);
433 g_signal_connect(expert_info_warn, "button_press_event", G_CALLBACK(expert_comp_dlg_cb), NULL);
435 expert_image = xpm_to_widget_from_parent(top_level, expert_note_xpm);
436 gtk_tooltips_set_tip(tooltips, expert_image, "NOTE is the highest expert info level", NULL);
437 gtk_widget_show(expert_image);
438 expert_info_note = gtk_event_box_new();
439 gtk_container_add(GTK_CONTAINER(expert_info_note), expert_image);
440 g_signal_connect(expert_info_note, "button_press_event", G_CALLBACK(expert_comp_dlg_cb), NULL);
442 expert_image = xpm_to_widget_from_parent(top_level, expert_chat_xpm);
443 gtk_tooltips_set_tip(tooltips, expert_image, "CHAT is the highest expert info level", NULL);
444 gtk_widget_show(expert_image);
445 expert_info_chat = gtk_event_box_new();
446 gtk_container_add(GTK_CONTAINER(expert_info_chat), expert_image);
447 g_signal_connect(expert_info_chat, "button_press_event", G_CALLBACK(expert_comp_dlg_cb), NULL);
449 expert_image = xpm_to_widget_from_parent(top_level, expert_none_xpm);
450 gtk_tooltips_set_tip(tooltips, expert_image, "No expert info", NULL);
451 gtk_widget_show(expert_image);
452 expert_info_none = gtk_event_box_new();
453 gtk_container_add(GTK_CONTAINER(expert_info_none), expert_image);
454 g_signal_connect(expert_info_none, "button_press_event", G_CALLBACK(expert_comp_dlg_cb), NULL);
455 gtk_widget_show(expert_info_none);
459 status_expert_hide(void)
461 /* reset expert info indicator */
462 gtk_widget_hide(expert_info_error);
463 gtk_widget_hide(expert_info_warn);
464 gtk_widget_hide(expert_info_note);
465 gtk_widget_hide(expert_info_chat);
466 gtk_widget_hide(expert_info_none);
470 status_expert_update(void)
472 status_expert_hide();
474 switch(expert_get_highest_severity()) {
476 gtk_widget_show(expert_info_error);
479 gtk_widget_show(expert_info_warn);
482 gtk_widget_show(expert_info_note);
485 gtk_widget_show(expert_info_chat);
488 gtk_widget_show(expert_info_none);
494 statusbar_set_filename(const char *file_name, gint64 file_length, nstime_t *file_elapsed_time)
499 /* expert info indicator */
500 status_expert_update();
503 /* convert file size */
504 if (file_length/1024/1024 > 10) {
505 size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d MB", file_length/1024/1024);
506 } else if (file_length/1024 > 10) {
507 size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d KB", file_length/1024);
509 size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d Bytes", file_length);
512 status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu",
513 (file_name) ? file_name : "", size_str,
514 (long)file_elapsed_time->secs/3600,
515 (long)file_elapsed_time->secs%3600/60,
516 (long)file_elapsed_time->secs%60);
518 statusbar_push_file_msg(status_msg);
524 statusbar_cf_file_closing_cb(capture_file *cf _U_)
526 /* Clear any file-related status bar messages.
527 XXX - should be "clear *ALL* file-related status bar messages;
528 will there ever be more than one on the stack? */
529 statusbar_pop_file_msg();
531 /* reset expert info indicator */
532 status_expert_hide();
533 gtk_widget_show(expert_info_none);
538 statusbar_cf_file_closed_cb(capture_file *cf _U_)
540 /* go back to "No packets" */
541 packets_bar_update();
546 statusbar_cf_file_read_start_cb(capture_file *cf)
548 const gchar *name_ptr;
551 /* Ensure we pop any previous loaded filename */
552 statusbar_pop_file_msg();
554 name_ptr = get_basename(cf->filename);
556 load_msg = g_strdup_printf(" Loading: %s", name_ptr);
557 statusbar_push_file_msg(load_msg);
563 statusbar_cf_file_read_finished_cb(capture_file *cf)
565 statusbar_pop_file_msg();
566 statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
572 statusbar_capture_prepared_cb(capture_options *capture_opts _U_)
574 statusbar_push_file_msg(" Waiting for capture input data ...");
578 statusbar_capture_update_started_cb(capture_options *capture_opts)
583 statusbar_pop_file_msg();
585 if(capture_opts->iface) {
586 capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
587 get_iface_description(capture_opts),
588 (capture_opts->save_file) ? capture_opts->save_file : "");
590 capture_msg = g_strdup_printf(" <live capture in progress> to file: %s",
591 (capture_opts->save_file) ? capture_opts->save_file : "");
594 statusbar_push_file_msg(capture_msg);
600 statusbar_capture_update_continue_cb(capture_options *capture_opts)
602 capture_file *cf = capture_opts->cf;
606 status_expert_update();
608 statusbar_pop_file_msg();
610 if (cf->f_datalen/1024/1024 > 10) {
611 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d MB",
612 get_iface_description(capture_opts),
613 capture_opts->save_file,
614 cf->f_datalen/1024/1024);
615 } else if (cf->f_datalen/1024 > 10) {
616 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d KB",
617 get_iface_description(capture_opts),
618 capture_opts->save_file,
621 capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d Bytes",
622 get_iface_description(capture_opts),
623 capture_opts->save_file,
627 statusbar_push_file_msg(capture_msg);
631 statusbar_capture_update_finished_cb(capture_options *capture_opts)
633 capture_file *cf = capture_opts->cf;
635 /* Pop the "<live capture in progress>" message off the status bar. */
636 statusbar_pop_file_msg();
637 statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
641 statusbar_capture_fixed_started_cb(capture_options *capture_opts)
646 statusbar_pop_file_msg();
648 capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
649 get_iface_description(capture_opts),
650 (capture_opts->save_file) ? capture_opts->save_file : "");
652 statusbar_push_file_msg(capture_msg);
653 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " Packets: 0");
659 statusbar_capture_fixed_continue_cb(capture_options *capture_opts)
661 capture_file *cf = capture_opts->cf;
665 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
666 capture_msg = g_strdup_printf(" Packets: %u", cf_get_packet_count(cf));
667 gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
673 statusbar_capture_fixed_finished_cb(capture_options *capture_opts _U_)
676 capture_file *cf = capture_opts->cf;
679 /* Pop the "<live capture in progress>" message off the status bar. */
680 statusbar_pop_file_msg();
682 /* Pop the "<capturing>" message off the status bar */
683 gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
686 #endif /* HAVE_LIBPCAP */
690 statusbar_cf_field_unselected_cb(capture_file *cf _U_)
692 statusbar_pop_field_msg();
696 statusbar_cf_file_safe_started_cb(gchar * filename)
700 save_msg = g_strdup_printf(" Saving: %s...", get_basename(filename));
701 statusbar_push_file_msg(save_msg);
706 statusbar_cf_file_safe_finished_cb(gpointer data _U_)
708 /* Pop the "Saving:" message off the status bar. */
709 statusbar_pop_file_msg();
713 statusbar_cf_file_safe_failed_cb(gpointer data _U_)
715 /* Pop the "Saving:" message off the status bar. */
716 statusbar_pop_file_msg();
722 statusbar_cf_callback(gint event, gpointer data, gpointer user_data _U_)
725 case(cf_cb_file_closing):
726 statusbar_cf_file_closing_cb(data);
728 case(cf_cb_file_closed):
729 statusbar_cf_file_closed_cb(data);
731 case(cf_cb_file_read_start):
732 statusbar_cf_file_read_start_cb(data);
734 case(cf_cb_file_read_finished):
735 statusbar_cf_file_read_finished_cb(data);
737 case(cf_cb_packet_selected):
739 case(cf_cb_packet_unselected):
741 case(cf_cb_field_unselected):
742 statusbar_cf_field_unselected_cb(data);
744 case(cf_cb_file_safe_started):
745 statusbar_cf_file_safe_started_cb(data);
747 case(cf_cb_file_safe_finished):
748 statusbar_cf_file_safe_finished_cb(data);
750 case(cf_cb_file_safe_reload_finished):
752 case(cf_cb_file_safe_failed):
753 statusbar_cf_file_safe_failed_cb(data);
756 g_warning("statusbar_cf_callback: event %u unknown", event);
757 g_assert_not_reached();
763 statusbar_capture_callback(gint event, capture_options *capture_opts,
764 gpointer user_data _U_)
767 case(capture_cb_capture_prepared):
768 statusbar_capture_prepared_cb(capture_opts);
770 case(capture_cb_capture_update_started):
771 statusbar_capture_update_started_cb(capture_opts);
773 case(capture_cb_capture_update_continue):
774 statusbar_capture_update_continue_cb(capture_opts);
776 case(capture_cb_capture_update_finished):
777 statusbar_capture_update_finished_cb(capture_opts);
779 case(capture_cb_capture_fixed_started):
780 statusbar_capture_fixed_started_cb(capture_opts);
782 case(capture_cb_capture_fixed_continue):
783 statusbar_capture_fixed_continue_cb(capture_opts);
785 case(capture_cb_capture_fixed_finished):
786 statusbar_capture_fixed_finished_cb(capture_opts);
788 case(capture_cb_capture_stopping):
789 /* Beware: this state won't be called, if the capture child
790 * closes the capturing on it's own! */
793 g_warning("statusbar_capture_callback: event %u unknown", event);
794 g_assert_not_reached();