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