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