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