Add text import capability, like text2pcap, directly into the GUI.
[obnox/wireshark/wip.git] / gtk / main_statusbar.c
1 /* main_statusbar.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
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.
13  *
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.
18  *
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.
22  */
23
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #include <gtk/gtk.h>
34
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>
40
41 #include "../cfile.h"
42 #include "../file.h"
43 #ifdef HAVE_LIBPCAP
44 #include "../capture_opts.h"
45 #include "../capture_ui_utils.h"
46 #include "../capture.h"
47 #endif
48
49 #include "gtk/recent.h"
50 #include "gtk/main.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"
57 #include "gtk/main_welcome.h"
58 #include "gtk/expert_indicators.h"
59 #include "gtk/keys.h"
60 #include "gtk/menus.h"
61
62 /*
63  * The order below defines the priority of info bar contexts.
64  */
65 typedef enum {
66     STATUS_LEVEL_MAIN,
67     STATUS_LEVEL_FILE,
68     STATUS_LEVEL_FILTER,
69     STATUS_LEVEL_HELP,
70     NUM_STATUS_LEVELS
71 } status_level_e;
72
73
74 #ifdef HAVE_LIBPCAP
75 #define DEF_READY_MESSAGE " Ready to load or capture"
76 #else
77 #define DEF_READY_MESSAGE " Ready to load file"
78 #endif
79
80
81 static GtkWidget    *status_pane_left, *status_pane_right;
82 static GtkWidget    *info_bar, *info_bar_event, *packets_bar, *profile_bar, *profile_bar_event;
83 static GtkWidget    *expert_info_error, *expert_info_warn, *expert_info_note;
84 static GtkWidget    *expert_info_chat, *expert_info_none;
85
86 static guint         main_ctx, file_ctx, help_ctx, filter_ctx, packets_ctx, profile_ctx;
87 static guint         status_levels[NUM_STATUS_LEVELS];
88 static gchar        *packets_str = NULL;
89 static gchar        *profile_str = NULL;
90
91
92 static void info_bar_new(void);
93 static void packets_bar_new(void);
94 static void profile_bar_new(void);
95 static void status_expert_new(void);
96
97 /* Temporary message timeouts */
98 #define TEMPORARY_MSG_TIMEOUT (7 * 1000)
99 #define TEMPORARY_FLASH_TIMEOUT (1 * 1000)
100 #define TEMPORARY_FLASH_INTERVAL (TEMPORARY_FLASH_TIMEOUT / 4)
101 static gint flash_time;
102 static gboolean flash_highlight = FALSE;
103
104 /*
105  * Push a message referring to file access onto the statusbar.
106  */
107 static void
108 statusbar_push_file_msg(const gchar *msg)
109 {
110     int i;
111
112     /*g_warning("statusbar_push: %s", msg);*/
113     for (i = STATUS_LEVEL_FILE + 1; i < NUM_STATUS_LEVELS; i++) {
114         if (status_levels[i])
115             return;
116     }
117     status_levels[STATUS_LEVEL_FILE]++;
118
119     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
120 }
121
122 /*
123  * Pop a message referring to file access off the statusbar.
124  */
125 static void
126 statusbar_pop_file_msg(void)
127 {
128     /*g_warning("statusbar_pop");*/
129     if (status_levels[STATUS_LEVEL_FILE] > 0) {
130         status_levels[STATUS_LEVEL_FILE]--;
131     }
132     gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
133 }
134
135 /*
136  * Push a message referring to the currently-selected field onto the statusbar.
137  */
138 void
139 statusbar_push_field_msg(const gchar *msg)
140 {
141     int i;
142
143     for (i = STATUS_LEVEL_HELP + 1; i < NUM_STATUS_LEVELS; i++) {
144         if (status_levels[i])
145             return;
146     }
147     status_levels[STATUS_LEVEL_HELP]++;
148
149     gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
150 }
151
152 /*
153  * Pop a message referring to the currently-selected field off the statusbar.
154  */
155 void
156 statusbar_pop_field_msg(void)
157 {
158     if (status_levels[STATUS_LEVEL_HELP] > 0) {
159         status_levels[STATUS_LEVEL_HELP]--;
160     }
161     gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
162 }
163
164 /*
165  * Push a message referring to the current filter onto the statusbar.
166  */
167 void
168 statusbar_push_filter_msg(const gchar *msg)
169 {
170     int i;
171
172     for (i = STATUS_LEVEL_FILTER + 1; i < NUM_STATUS_LEVELS; i++) {
173         if (status_levels[i])
174             return;
175     }
176     status_levels[STATUS_LEVEL_FILTER]++;
177
178     gtk_statusbar_push(GTK_STATUSBAR(info_bar), filter_ctx, msg);
179 }
180
181 /*
182  * Pop a message referring to the current filter off the statusbar.
183  */
184 void
185 statusbar_pop_filter_msg(void)
186 {
187     if (status_levels[STATUS_LEVEL_FILTER] > 0) {
188         status_levels[STATUS_LEVEL_FILTER]--;
189     }
190     gtk_statusbar_pop(GTK_STATUSBAR(info_bar), filter_ctx);
191 }
192
193 /*
194  * Timeout callbacks for statusbar_push_temporary_msg
195  */
196 static gboolean
197 statusbar_remove_temporary_msg(gpointer data)
198 {
199     guint msg_id = GPOINTER_TO_UINT(data);
200
201     gtk_statusbar_remove(GTK_STATUSBAR(info_bar), main_ctx, msg_id);
202
203     return FALSE;
204 }
205
206 static gboolean
207 statusbar_flash_temporary_msg(gpointer data _U_)
208 {
209     gboolean retval = TRUE;
210
211     if (flash_time > 0) {
212         flash_highlight = !flash_highlight;
213     } else {
214         flash_highlight = FALSE;
215         retval = FALSE;
216     }
217
218     /*
219      * As of 2.18.3 gtk_drag_highlight just draws a border around the widget
220      * so we can abuse it here.
221      */
222     if (flash_highlight) {
223         gtk_drag_highlight(info_bar);
224     } else {
225         gtk_drag_unhighlight(info_bar);
226     }
227
228     flash_time -= TEMPORARY_FLASH_INTERVAL;
229
230     return retval;
231 }
232
233 /*
234  * Push a temporary message onto the statusbar.
235  */
236 void
237 statusbar_push_temporary_msg(const gchar *msg)
238 {
239     guint msg_id;
240
241     msg_id = gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, msg);
242
243     flash_time = TEMPORARY_FLASH_TIMEOUT - 1;
244     g_timeout_add(TEMPORARY_FLASH_INTERVAL, statusbar_flash_temporary_msg, NULL);
245
246     g_timeout_add(TEMPORARY_MSG_TIMEOUT, statusbar_remove_temporary_msg, GUINT_TO_POINTER(msg_id));
247 }
248
249
250 GtkWidget *
251 statusbar_new(void)
252 {
253     GtkWidget *status_hbox;
254
255     /* Status hbox */
256     status_hbox = gtk_hbox_new(FALSE, 1);
257     gtk_container_set_border_width(GTK_CONTAINER(status_hbox), 0);
258
259     /* info (main) statusbar */
260     info_bar_new();
261
262     /* packets statusbar */
263     packets_bar_new();
264
265     /* profile statusbar */
266     profile_bar_new();
267
268     /* expert info indicator */
269     status_expert_new();
270
271     /* Pane for the statusbar */
272     status_pane_left = gtk_hpaned_new();
273     gtk_widget_show(status_pane_left);
274     status_pane_right = gtk_hpaned_new();
275     gtk_widget_show(status_pane_right);
276
277     return status_hbox;
278 }
279
280 void
281 statusbar_load_window_geometry(void)
282 {
283     if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_left)
284         gtk_paned_set_position(GTK_PANED(status_pane_left), recent.gui_geometry_status_pane_left);
285     if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_right)
286         gtk_paned_set_position(GTK_PANED(status_pane_right), recent.gui_geometry_status_pane_right);
287 }
288
289 void
290 statusbar_save_window_geometry(void)
291 {
292     recent.gui_geometry_status_pane_left    = gtk_paned_get_position(GTK_PANED(status_pane_left));
293     recent.gui_geometry_status_pane_right   = gtk_paned_get_position(GTK_PANED(status_pane_right));
294 }
295
296
297 /*
298  * Helper for statusbar_widgets_emptying()
299  */
300 static void
301 foreach_remove_a_child(GtkWidget *widget, gpointer data) {
302     gtk_container_remove(GTK_CONTAINER(data), widget);
303 }
304
305 void
306 statusbar_widgets_emptying(GtkWidget *statusbar)
307 {
308     g_object_ref(G_OBJECT(info_bar));
309     g_object_ref(G_OBJECT(info_bar_event));
310     g_object_ref(G_OBJECT(packets_bar));
311     g_object_ref(G_OBJECT(profile_bar));
312     g_object_ref(G_OBJECT(profile_bar_event));
313     g_object_ref(G_OBJECT(status_pane_left));
314     g_object_ref(G_OBJECT(status_pane_right));
315     g_object_ref(G_OBJECT(expert_info_error));
316     g_object_ref(G_OBJECT(expert_info_warn));
317     g_object_ref(G_OBJECT(expert_info_note));
318     g_object_ref(G_OBJECT(expert_info_chat));
319     g_object_ref(G_OBJECT(expert_info_none));
320
321     /* empty all containers participating */
322     gtk_container_foreach(GTK_CONTAINER(statusbar),     foreach_remove_a_child, statusbar);
323     gtk_container_foreach(GTK_CONTAINER(status_pane_left),   foreach_remove_a_child, status_pane_left);
324     gtk_container_foreach(GTK_CONTAINER(status_pane_right),   foreach_remove_a_child, status_pane_right);
325 }
326
327 void
328 statusbar_widgets_pack(GtkWidget *statusbar)
329 {
330     gtk_box_pack_start(GTK_BOX(statusbar), expert_info_error, FALSE, FALSE, 2);
331     gtk_box_pack_start(GTK_BOX(statusbar), expert_info_warn, FALSE, FALSE, 2);
332     gtk_box_pack_start(GTK_BOX(statusbar), expert_info_note, FALSE, FALSE, 2);
333     gtk_box_pack_start(GTK_BOX(statusbar), expert_info_chat, FALSE, FALSE, 2);
334     gtk_box_pack_start(GTK_BOX(statusbar), expert_info_none, FALSE, FALSE, 2);
335     gtk_box_pack_start(GTK_BOX(statusbar), status_pane_left, TRUE, TRUE, 0);
336     gtk_paned_pack1(GTK_PANED(status_pane_left), info_bar_event, FALSE, FALSE);
337     gtk_paned_pack2(GTK_PANED(status_pane_left), status_pane_right, TRUE, FALSE);
338     gtk_paned_pack1(GTK_PANED(status_pane_right), packets_bar, TRUE, FALSE);
339     gtk_paned_pack2(GTK_PANED(status_pane_right), profile_bar_event, FALSE, FALSE);
340 }
341
342 void
343 statusbar_widgets_show_or_hide(GtkWidget *statusbar)
344 {
345     /*
346      * Show the status hbox if either:
347      *
348      *    1) we're showing the filter toolbar and we want it in the status
349      *       line
350      *
351      * or
352      *
353      *    2) we're showing the status bar.
354      */
355     if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
356          recent.statusbar_show) {
357         gtk_widget_show(statusbar);
358     } else {
359         gtk_widget_hide(statusbar);
360     }
361
362     if (recent.statusbar_show) {
363         gtk_widget_show(status_pane_left);
364     } else {
365         gtk_widget_hide(status_pane_left);
366     }
367 }
368
369
370 static void
371 info_bar_new(void)
372 {
373     int i;
374
375     info_bar_event = gtk_event_box_new();
376     info_bar = gtk_statusbar_new();
377     gtk_container_add(GTK_CONTAINER(info_bar_event), info_bar);
378     main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
379     file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
380     help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
381     filter_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "filter");
382     gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
383     gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
384
385     for (i = 0; i < NUM_STATUS_LEVELS; i++) {
386         status_levels[i] = 0;
387     }
388
389     gtk_widget_show(info_bar);
390     gtk_widget_show(info_bar_event);
391 }
392
393 static void
394 packets_bar_new(void)
395 {
396     /* tip: tooltips don't work on statusbars! */
397     packets_bar = gtk_statusbar_new();
398     packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
399     packets_bar_update();
400     gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(packets_bar), FALSE);
401
402     gtk_widget_show(packets_bar);
403 }
404
405 static void
406 profile_bar_new(void)
407 {
408     GtkTooltips   *tooltips;
409
410     tooltips = gtk_tooltips_new();
411
412     profile_bar_event = gtk_event_box_new();
413     profile_bar = gtk_statusbar_new();
414     gtk_container_add(GTK_CONTAINER(profile_bar_event), profile_bar);
415     g_signal_connect(profile_bar_event, "button_press_event", G_CALLBACK(profile_show_popup_cb), NULL);
416     g_signal_connect(profile_bar_event, "button_press_event", G_CALLBACK(popup_menu_handler),
417                      g_object_get_data(G_OBJECT(popup_menu_object), PM_STATUSBAR_PROFILES_KEY));
418     profile_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(profile_bar), "profile");
419     gtk_tooltips_set_tip (tooltips, profile_bar_event,
420                           "Click to change configuration profile", NULL);
421     profile_bar_update();
422
423     gtk_widget_show(profile_bar);
424     gtk_widget_show(profile_bar_event);
425 }
426
427
428 /*
429  * Update the packets statusbar to the current values
430  */
431 void
432 packets_bar_update(void)
433 {
434     if(packets_bar) {
435         /* Remove old status */
436         if(packets_str) {
437             g_free(packets_str);
438             gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
439         }
440
441         /* Do we have any packets? */
442         if(cfile.count) {
443             if(cfile.drops_known) {
444                 packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u Dropped: %u",
445                     cfile.count, cfile.displayed_count, cfile.marked_count, cfile.drops);
446             } else if (cfile.ignored_count > 0) {
447                 packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u Ignored: %u",
448                     cfile.count, cfile.displayed_count, cfile.marked_count, cfile.ignored_count);
449             } else {
450                 if(cfile.is_tempfile){
451                     /* Live capture */
452                     packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u",
453                                                   cfile.count, cfile.displayed_count, cfile.marked_count);
454                 }else{
455                     /* Loading an existing file */
456                     gulong computed_elapsed = cf_get_computed_elapsed();
457                     packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u Load time: %lu:%02lu.%03lu",
458                                                   cfile.count, cfile.displayed_count, cfile.marked_count,
459                                                   computed_elapsed/60000,
460                                                   computed_elapsed%60000/1000,
461                                                   computed_elapsed%1000);
462                 }
463             }
464         } else {
465             packets_str = g_strdup(" No Packets");
466         }
467         gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
468     }
469 }
470
471 /*
472  * Update the packets statusbar to the current values
473  */
474 void
475 profile_bar_update(void)
476 {
477     if (profile_bar) {
478         /* remove old status */
479         if(profile_str) {
480             g_free(profile_str);
481             gtk_statusbar_pop(GTK_STATUSBAR(profile_bar), profile_ctx);
482         }
483
484         profile_str = g_strdup_printf (" Profile: %s", get_profile_name ());
485         gtk_statusbar_push(GTK_STATUSBAR(profile_bar), profile_ctx, profile_str);
486
487         set_menus_for_profiles(is_default_profile());
488     }
489 }
490
491 static gboolean
492 expert_comp_dlg_event_cb(GtkWidget *w _U_, GdkEventButton *event _U_, gpointer user_data _U_)
493 {
494     expert_comp_dlg_launch();
495     return TRUE;
496 }
497
498 static void
499 status_expert_new(void)
500 {
501     GtkWidget *expert_image;
502     GtkTooltips   *tooltips;
503
504     tooltips = gtk_tooltips_new();
505
506     expert_image = pixbuf_to_widget(expert_error_pb_data);
507     gtk_tooltips_set_tip(tooltips, expert_image, "ERROR is the highest expert info level", NULL);
508     gtk_widget_show(expert_image);
509     expert_info_error = gtk_event_box_new();
510     gtk_container_add(GTK_CONTAINER(expert_info_error), expert_image);
511     g_signal_connect(expert_info_error, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
512
513     expert_image = pixbuf_to_widget(expert_warn_pb_data);
514     gtk_tooltips_set_tip(tooltips, expert_image, "WARNING is the highest expert info level", NULL);
515     gtk_widget_show(expert_image);
516     expert_info_warn = gtk_event_box_new();
517     gtk_container_add(GTK_CONTAINER(expert_info_warn), expert_image);
518     g_signal_connect(expert_info_warn, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
519
520     expert_image = pixbuf_to_widget(expert_note_pb_data);
521     gtk_tooltips_set_tip(tooltips, expert_image, "NOTE is the highest expert info level", NULL);
522     gtk_widget_show(expert_image);
523     expert_info_note = gtk_event_box_new();
524     gtk_container_add(GTK_CONTAINER(expert_info_note), expert_image);
525     g_signal_connect(expert_info_note, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
526
527     expert_image = pixbuf_to_widget(expert_chat_pb_data);
528     gtk_tooltips_set_tip(tooltips, expert_image, "CHAT is the highest expert info level", NULL);
529     gtk_widget_show(expert_image);
530     expert_info_chat = gtk_event_box_new();
531     gtk_container_add(GTK_CONTAINER(expert_info_chat), expert_image);
532     g_signal_connect(expert_info_chat, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
533
534     expert_image = pixbuf_to_widget(expert_none_pb_data);
535     gtk_tooltips_set_tip(tooltips, expert_image, "No expert info", NULL);
536     gtk_widget_show(expert_image);
537     expert_info_none = gtk_event_box_new();
538     gtk_container_add(GTK_CONTAINER(expert_info_none), expert_image);
539     g_signal_connect(expert_info_none, "button_press_event", G_CALLBACK(expert_comp_dlg_event_cb), NULL);
540     gtk_widget_show(expert_info_none);
541 }
542
543 static void
544 status_expert_hide(void)
545 {
546     /* reset expert info indicator */
547     gtk_widget_hide(expert_info_error);
548     gtk_widget_hide(expert_info_warn);
549     gtk_widget_hide(expert_info_note);
550     gtk_widget_hide(expert_info_chat);
551     gtk_widget_hide(expert_info_none);
552 }
553
554 void
555 status_expert_update(void)
556 {
557     status_expert_hide();
558
559     switch(expert_get_highest_severity()) {
560     case(PI_ERROR):
561         gtk_widget_show(expert_info_error);
562         break;
563     case(PI_WARN):
564         gtk_widget_show(expert_info_warn);
565         break;
566     case(PI_NOTE):
567         gtk_widget_show(expert_info_note);
568         break;
569     case(PI_CHAT):
570         gtk_widget_show(expert_info_chat);
571         break;
572     default:
573         gtk_widget_show(expert_info_none);
574         break;
575     }
576 }
577
578 static void
579 statusbar_set_filename(const char *file_name, gint64 file_length, nstime_t *file_elapsed_time)
580 {
581     gchar       *size_str;
582     gchar       *status_msg;
583
584     /* expert info indicator */
585     status_expert_update();
586
587     /* statusbar */
588     /* convert file size */
589     if (file_length/1024/1024 > 10) {
590         size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d MB", file_length/1024/1024);
591     } else if (file_length/1024 > 10) {
592         size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d KB", file_length/1024);
593     } else {
594         size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d Bytes", file_length);
595     }
596
597     status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu",
598                                  (file_name) ? file_name : "", size_str,
599                                  (long)file_elapsed_time->secs/3600,
600                                  (long)file_elapsed_time->secs%3600/60,
601                                  (long)file_elapsed_time->secs%60);
602     g_free(size_str);
603     statusbar_push_file_msg(status_msg);
604     g_free(status_msg);
605 }
606
607
608 static void
609 statusbar_cf_file_closing_cb(capture_file *cf _U_)
610 {
611     /* Clear any file-related status bar messages.
612        XXX - should be "clear *ALL* file-related status bar messages;
613        will there ever be more than one on the stack? */
614     statusbar_pop_file_msg();
615
616     /* reset expert info indicator */
617     status_expert_hide();
618     gtk_widget_show(expert_info_none);
619 }
620
621
622 static void
623 statusbar_cf_file_closed_cb(capture_file *cf _U_)
624 {
625     /* go back to "No packets" */
626     packets_bar_update();
627 }
628
629
630 static void
631 statusbar_cf_file_read_started_cb(capture_file *cf)
632 {
633     const gchar *name_ptr;
634     gchar       *load_msg;
635
636     /* Ensure we pop any previous loaded filename */
637     statusbar_pop_file_msg();
638
639     name_ptr = get_basename(cf->filename);
640
641     load_msg = g_strdup_printf(" Loading: %s", name_ptr);
642     statusbar_push_file_msg(load_msg);
643     g_free(load_msg);
644 }
645
646
647 static void
648 statusbar_cf_file_read_finished_cb(capture_file *cf)
649 {
650     statusbar_pop_file_msg();
651     statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
652 }
653
654
655 #ifdef HAVE_LIBPCAP
656 static void
657 statusbar_capture_prepared_cb(capture_options *capture_opts _U_)
658 {
659     gchar *msg = " Waiting for capture input data ...";
660     statusbar_push_file_msg(msg);
661     welcome_header_push_msg(msg);
662 }
663
664 static void
665 statusbar_capture_update_started_cb(capture_options *capture_opts)
666 {
667     gchar *capture_msg;
668
669
670     statusbar_pop_file_msg();
671     welcome_header_pop_msg();
672
673     if(capture_opts->iface) {
674         capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
675                                       get_iface_description(capture_opts),
676                                       (capture_opts->save_file) ? capture_opts->save_file : "");
677     } else {
678         capture_msg = g_strdup_printf(" <live capture in progress> to file: %s",
679             (capture_opts->save_file) ? capture_opts->save_file : "");
680     }
681
682     statusbar_push_file_msg(capture_msg);
683
684     g_free(capture_msg);
685 }
686
687 static void
688 statusbar_capture_update_continue_cb(capture_options *capture_opts)
689 {
690     capture_file *cf = capture_opts->cf;
691     gchar *capture_msg;
692
693
694     status_expert_update();
695
696     statusbar_pop_file_msg();
697
698     if (cf->f_datalen/1024/1024 > 10) {
699         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d MB",
700                                       get_iface_description(capture_opts),
701                                       capture_opts->save_file,
702                                       cf->f_datalen/1024/1024);
703     } else if (cf->f_datalen/1024 > 10) {
704         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d KB",
705                                       get_iface_description(capture_opts),
706                                       capture_opts->save_file,
707                                       cf->f_datalen/1024);
708     } else {
709         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d Bytes",
710                                       get_iface_description(capture_opts),
711                                       capture_opts->save_file,
712                                       cf->f_datalen);
713     }
714
715     statusbar_push_file_msg(capture_msg);
716 }
717
718 static void
719 statusbar_capture_update_finished_cb(capture_options *capture_opts)
720 {
721     capture_file *cf = capture_opts->cf;
722
723     /* Pop the "<live capture in progress>" message off the status bar. */
724     statusbar_pop_file_msg();
725     statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
726     packets_bar_update();
727 }
728
729 static void
730 statusbar_capture_fixed_started_cb(capture_options *capture_opts)
731 {
732     gchar *capture_msg;
733
734
735     statusbar_pop_file_msg();
736
737     capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
738                                   get_iface_description(capture_opts),
739                                   (capture_opts->save_file) ? capture_opts->save_file : "");
740
741     statusbar_push_file_msg(capture_msg);
742     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " Packets: 0");
743
744     g_free(capture_msg);
745 }
746
747 static void
748 statusbar_capture_fixed_continue_cb(capture_options *capture_opts)
749 {
750     capture_file *cf = capture_opts->cf;
751     gchar *capture_msg;
752
753
754     gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
755     capture_msg = g_strdup_printf(" Packets: %u", cf_get_packet_count(cf));
756     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
757     g_free(capture_msg);
758 }
759
760
761 static void
762 statusbar_capture_fixed_finished_cb(capture_options *capture_opts _U_)
763 {
764 #if 0
765     capture_file *cf = capture_opts->cf;
766 #endif
767
768     /* Pop the "<live capture in progress>" message off the status bar. */
769     statusbar_pop_file_msg();
770     welcome_header_pop_msg();
771
772     /* Pop the "<capturing>" message off the status bar */
773     gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
774 }
775
776 #endif /* HAVE_LIBPCAP */
777
778
779 static void
780 statusbar_cf_field_unselected_cb(capture_file *cf _U_)
781 {
782     statusbar_pop_field_msg();
783 }
784
785 static void
786 statusbar_cf_file_save_started_cb(gchar *filename)
787 {
788     gchar        *save_msg;
789
790     statusbar_pop_file_msg();
791     save_msg = g_strdup_printf(" Saving: %s...", get_basename(filename));
792     statusbar_push_file_msg(save_msg);
793     g_free(save_msg);
794 }
795
796 static void
797 statusbar_cf_file_save_finished_cb(gpointer data _U_)
798 {
799     /* Pop the "Saving:" message off the status bar. */
800     statusbar_pop_file_msg();
801 }
802
803 static void
804 statusbar_cf_file_reload_finished_cb(capture_file *cf)
805 {
806     statusbar_pop_file_msg();
807     statusbar_set_filename(cf->filename, cf->f_datalen, &(cf->elapsed_time));
808 }
809
810
811 static void
812 statusbar_cf_file_save_failed_cb(gpointer data _U_)
813 {
814     /* Pop the "Saving:" message off the status bar. */
815     statusbar_pop_file_msg();
816 }
817
818
819
820 void
821 statusbar_cf_callback(gint event, gpointer data, gpointer user_data _U_)
822 {
823     switch(event) {
824     case(cf_cb_file_closing):
825         statusbar_cf_file_closing_cb(data);
826         break;
827     case(cf_cb_file_closed):
828         statusbar_cf_file_closed_cb(data);
829         break;
830     case(cf_cb_file_read_started):
831         statusbar_cf_file_read_started_cb(data);
832         break;
833     case(cf_cb_file_read_finished):
834         statusbar_cf_file_read_finished_cb(data);
835         break;
836     case(cf_cb_packet_selected):
837         break;
838     case(cf_cb_packet_unselected):
839         break;
840     case(cf_cb_field_unselected):
841         statusbar_cf_field_unselected_cb(data);
842         break;
843     case(cf_cb_file_save_started):
844         statusbar_cf_file_save_started_cb(data);
845         break;
846     case(cf_cb_file_save_finished):
847         statusbar_cf_file_save_finished_cb(data);
848         break;
849     case(cf_cb_file_save_reload_finished):
850         statusbar_cf_file_reload_finished_cb(data);
851         break;
852     case(cf_cb_file_save_failed):
853         statusbar_cf_file_save_failed_cb(data);
854         break;
855     default:
856         g_warning("statusbar_cf_callback: event %u unknown", event);
857         g_assert_not_reached();
858     }
859 }
860
861 #ifdef HAVE_LIBPCAP
862 void
863 statusbar_capture_callback(gint event, capture_options *capture_opts,
864                            gpointer user_data _U_)
865 {
866     switch(event) {
867     case(capture_cb_capture_prepared):
868         statusbar_capture_prepared_cb(capture_opts);
869         break;
870     case(capture_cb_capture_update_started):
871         statusbar_capture_update_started_cb(capture_opts);
872         break;
873     case(capture_cb_capture_update_continue):
874         statusbar_capture_update_continue_cb(capture_opts);
875         break;
876     case(capture_cb_capture_update_finished):
877         statusbar_capture_update_finished_cb(capture_opts);
878         break;
879     case(capture_cb_capture_fixed_started):
880         statusbar_capture_fixed_started_cb(capture_opts);
881         break;
882     case(capture_cb_capture_fixed_continue):
883         statusbar_capture_fixed_continue_cb(capture_opts);
884         break;
885     case(capture_cb_capture_fixed_finished):
886         statusbar_capture_fixed_finished_cb(capture_opts);
887         break;
888     case(capture_cb_capture_stopping):
889         /* Beware: this state won't be called, if the capture child
890          * closes the capturing on it's own! */
891         break;
892     default:
893         g_warning("statusbar_capture_callback: event %u unknown", event);
894         g_assert_not_reached();
895     }
896 }
897 #endif