5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
35 #include <epan/prefs.h>
40 #include "capture-pcap-util.h"
41 #include "capture_opts.h"
42 #include "capture_ui_utils.h"
44 #include "simple_dialog.h"
45 #include <wsutil/file_util.h>
47 #include "gtk/gui_utils.h"
48 #include "gtk/color_utils.h"
49 #include "gtk/recent.h"
50 #include "gtk/gtkglobals.h"
52 #include "gtk/menus.h"
53 #include "gtk/main_welcome.h"
54 #include "gtk/help_dlg.h"
55 #include "gtk/capture_file_dlg.h"
56 #include "gtk/stock_icons.h"
57 #include "gtk/utf8_entities.h"
59 #include "gtk/capture_dlg.h"
60 #include "gtk/capture_if_dlg.h"
61 #include "gtk/capture_globals.h"
63 #include "../image/wssplash-dev.xpm"
64 #include "../version_info.h"
73 #include "airpcap_loader.h"
74 #include "airpcap_gui_utils.h"
76 #if defined(HAVE_AIRPCAP) || defined(HAVE_PCAP_REMOTE)
77 #include "../image/toolbar/capture_airpcap_16.xpm"
81 extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg);
83 static GtkWidget *welcome_hb = NULL;
84 static GtkWidget *header_lb = NULL;
85 /* Foreground colors are set using Pango markup */
86 #if GTK_CHECK_VERSION(3,0,0)
87 static GdkRGBA rgba_welcome_bg = {0.901, 0.901, 0.901, 1.0 };
88 static GdkRGBA rgba_header_bar_bg = { 0.094, 0.360, 0.792, 1.0 };
89 static GdkRGBA rgba_topic_header_bg = { 0.004, 0.224, 0.745, 1.0 };
90 static GdkRGBA rgba_topic_content_bg = { 1, 1, 1, 1.0 };
91 static GdkRGBA rgba_topic_item_idle_bg;
92 static GdkRGBA rgba_topic_item_entered_bg = { 0.827, 0.847, 0.854, 1.0 };
94 static GdkColor welcome_bg = { 0, 0xe6e6, 0xe6e6, 0xe6e6 };
95 static GdkColor header_bar_bg = { 0, 0x1818, 0x5c5c, 0xcaca };
96 static GdkColor topic_header_bg = { 0, 0x0101, 0x3939, 0xbebe };
97 static GdkColor topic_content_bg = { 0, 0xffff, 0xffff, 0xffff };
98 static GdkColor topic_item_idle_bg;
99 static GdkColor topic_item_entered_bg = { 0, 0xd3d3, 0xd8d8, 0xdada };
101 static GtkWidget *welcome_file_panel_vb = NULL;
103 static GtkWidget *welcome_if_panel_vb = NULL;
104 static GtkWidget *if_view = NULL;
105 static GtkWidget *swindow;
106 static GArray *interfaces = NULL;
109 static GSList *status_messages = NULL;
112 static GMutex *recent_mtx = NULL;
115 /* The "scroll box dynamic" is a (complicated) pseudo widget to */
116 /* place a vertically list of widgets in (currently the interfaces and recent files). */
117 /* Once this list get's higher than a specified amount, */
118 /* it is moved into a scrolled_window. */
119 /* This is all complicated, the scrolled window is a bit ugly, */
120 /* the sizes might not be the same on all systems, ... */
121 /* ... but that's the best what we currently have */
122 #define SCROLL_BOX_CHILD_BOX "ScrollBoxDynamic_ChildBox"
123 #define SCROLL_BOX_MAX_CHILDS "ScrollBoxDynamic_MaxChilds"
124 #define SCROLL_BOX_SCROLLW_Y_SIZE "ScrollBoxDynamic_Scrollw_Y_Size"
125 #define SCROLL_BOX_SCROLLW "ScrollBoxDynamic_Scrollw"
126 #define TREE_VIEW_INTERFACES "TreeViewInterfaces"
129 scroll_box_dynamic_new(GtkWidget *child_box, guint max_childs, guint scrollw_y_size) {
130 GtkWidget * parent_box;
133 parent_box = gtk_vbox_new(FALSE, 0);
134 gtk_box_pack_start(GTK_BOX(parent_box), GTK_WIDGET(child_box), TRUE, TRUE, 0);
135 g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_CHILD_BOX, child_box);
136 g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_MAX_CHILDS, GINT_TO_POINTER(max_childs));
137 g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW_Y_SIZE, GINT_TO_POINTER(scrollw_y_size));
138 gtk_widget_show_all(parent_box);
145 scroll_box_dynamic_add(GtkWidget *parent_box)
147 GtkWidget *child_box;
151 guint scrollw_y_size;
154 child_box = g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_CHILD_BOX);
155 max_cnt = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_MAX_CHILDS));
157 /* get the current number of children */
158 childs = gtk_container_get_children(GTK_CONTAINER(child_box));
159 curr_cnt = g_list_length(childs);
162 /* have we just reached the max? */
163 if(curr_cnt == max_cnt) {
164 /* create the scrolled window */
165 /* XXX - there's no way to get rid of the shadow frame - except for creating an own widget :-( */
166 scrollw = scrolled_window_new(NULL, NULL);
167 scrollw_y_size = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW_Y_SIZE));
168 gtk_widget_set_size_request(scrollw, -1, scrollw_y_size);
170 g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW, scrollw);
171 gtk_box_pack_start(GTK_BOX(parent_box), scrollw, TRUE, TRUE, 0);
173 /* move child_box from parent_box into scrolled window */
174 g_object_ref(child_box);
175 gtk_container_remove(GTK_CONTAINER(parent_box), child_box);
176 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollw),
178 gtk_widget_show_all(scrollw);
186 scroll_box_dynamic_reset(GtkWidget *parent_box)
188 GtkWidget *child_box, *scrollw;
191 child_box = g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_CHILD_BOX);
192 scrollw = g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW);
194 if(scrollw != NULL) {
195 /* move the child_box back from scrolled window into the parent_box */
196 g_object_ref(child_box);
197 gtk_container_remove(GTK_CONTAINER(parent_box), scrollw);
198 g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW, NULL);
199 gtk_box_pack_start(GTK_BOX(parent_box), child_box, TRUE, TRUE, 0);
206 /* mouse entered this widget - change background color */
208 welcome_item_enter_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_)
210 #if GTK_CHECK_VERSION(3,0,0)
211 gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_entered_bg);
213 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_entered_bg);
219 /* mouse has left this widget - change background color */
221 welcome_item_leave_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_)
223 #if GTK_CHECK_VERSION(3,0,0)
224 gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
226 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
232 typedef gboolean (*welcome_button_callback_t) (GtkWidget *widget,
233 GdkEventButton *event,
236 /* create a "button widget" */
238 welcome_button(const gchar *stock_item,
239 const gchar *title, const gchar *subtitle, const gchar *tooltip,
240 welcome_button_callback_t welcome_button_callback, gpointer welcome_button_callback_data)
242 GtkWidget *eb, *w, *item_hb, *text_vb;
243 gchar *formatted_text;
245 item_hb = gtk_hbox_new(FALSE, 1);
247 /* event box (for background color and events) */
248 eb = gtk_event_box_new();
249 gtk_container_add(GTK_CONTAINER(eb), item_hb);
250 #if GTK_CHECK_VERSION(3,0,0)
251 gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
253 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
255 if(tooltip != NULL) {
256 gtk_widget_set_tooltip_text(eb, tooltip);
259 g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), NULL);
260 g_signal_connect(eb, "leave-notify-event", G_CALLBACK(welcome_item_leave_cb), NULL);
261 g_signal_connect(eb, "button-release-event", G_CALLBACK(welcome_button_callback), welcome_button_callback_data);
264 w = gtk_image_new_from_stock(stock_item, GTK_ICON_SIZE_LARGE_TOOLBAR);
265 gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 5);
267 text_vb = gtk_vbox_new(FALSE, 3);
270 w = gtk_label_new(title);
271 gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.5f);
272 formatted_text = g_strdup_printf("<span weight=\"bold\" size=\"x-large\" foreground=\"black\">%s</span>", title);
273 gtk_label_set_markup(GTK_LABEL(w), formatted_text);
274 g_free(formatted_text);
275 gtk_box_pack_start(GTK_BOX(text_vb), w, FALSE, FALSE, 1);
278 w = gtk_label_new(subtitle);
279 gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.5f);
280 formatted_text = g_strdup_printf("<span size=\"small\" foreground=\"black\">%s</span>", subtitle);
281 gtk_label_set_markup(GTK_LABEL(w), formatted_text);
282 g_free(formatted_text);
283 gtk_box_pack_start(GTK_BOX(text_vb), w, FALSE, FALSE, 1);
285 gtk_box_pack_start(GTK_BOX(item_hb), text_vb, TRUE, TRUE, 5);
291 /* Hack to handle welcome-button "button-release-event" callback */
292 /* 1. Dispatch to desired actual callback */
293 /* 2. Return TRUE for the event callback. */
294 /* user_data: actual (no arg) callback fcn to be invoked. */
296 welcome_button_callback_helper(GtkWidget *w, GdkEventButton *event _U_, gpointer user_data)
298 void (*funct)(GtkWidget *, gpointer) = user_data;
305 welcome_header_set_message(gchar *msg) {
307 time_t secs = time(NULL);
308 struct tm *now = localtime(&secs);
310 message = g_string_new("<span weight=\"bold\" size=\"x-large\" foreground=\"white\">");
313 g_string_append(message, msg);
314 } else { /* Use our default header */
315 if ((now->tm_mon == 3 && now->tm_mday == 1) || (now->tm_mon == 6 && now->tm_mday == 14)) {
316 g_string_append(message, "Sniffing the glue that holds the Internet together");
318 g_string_append(message, prefs.gui_start_title);
321 if (prefs.gui_version_in_start_page) {
322 g_string_append_printf(message, "</span>\n<span size=\"large\" foreground=\"white\">Version " VERSION "%s",
323 wireshark_svnversion);
327 g_string_append(message, "</span>");
329 gtk_label_set_markup(GTK_LABEL(header_lb), message->str);
330 g_string_free(message, TRUE);
334 /* create the banner "above our heads" */
336 welcome_header_new(void)
343 item_vb = gtk_vbox_new(FALSE, 0);
346 eb = gtk_event_box_new();
347 gtk_container_add(GTK_CONTAINER(eb), item_vb);
348 #if GTK_CHECK_VERSION(3,0,0)
349 gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_header_bar_bg);
351 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &header_bar_bg);
353 item_hb = gtk_hbox_new(FALSE, 0);
354 gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10);
356 /*icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);*/
357 icon = xpm_to_widget(wssplash_xpm);
358 gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10);
360 header_lb = gtk_label_new(NULL);
361 welcome_header_set_message(NULL);
362 gtk_label_set_selectable(GTK_LABEL(header_lb), TRUE);
363 gtk_misc_set_alignment(GTK_MISC(header_lb), 0.0f, 0.5f);
364 gtk_box_pack_start(GTK_BOX(item_hb), header_lb, TRUE, TRUE, 5);
366 gtk_widget_show_all(eb);
373 welcome_header_push_msg(const gchar *msg) {
374 gchar *msg_copy = g_strdup(msg);
376 status_messages = g_slist_append(status_messages, msg_copy);
378 welcome_header_set_message(msg_copy);
380 gtk_widget_hide(welcome_hb);
385 welcome_header_pop_msg(void) {
388 if (status_messages) {
389 g_free(status_messages->data);
390 status_messages = g_slist_delete_link(status_messages, status_messages);
393 if (status_messages) {
394 msg = status_messages->data;
397 welcome_header_set_message(msg);
399 if (!status_messages) {
400 gtk_widget_show(welcome_hb);
405 /* create a "topic header widget" */
407 welcome_topic_header_new(const char *header)
411 gchar *formatted_message;
414 w = gtk_label_new(header);
415 formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\" foreground=\"white\">%s</span>", header);
416 gtk_label_set_markup(GTK_LABEL(w), formatted_message);
417 g_free(formatted_message);
420 eb = gtk_event_box_new();
421 gtk_container_add(GTK_CONTAINER(eb), w);
422 #if GTK_CHECK_VERSION(3,0,0)
423 gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_header_bg);
425 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_header_bg);
431 /* create a "topic widget" */
433 welcome_topic_new(const char *header, GtkWidget **to_fill)
436 GtkWidget *layout_vb;
438 GtkWidget *topic_header;
441 topic_vb = gtk_vbox_new(FALSE, 0);
443 topic_header = welcome_topic_header_new(header);
444 gtk_box_pack_start(GTK_BOX(topic_vb), topic_header, FALSE, FALSE, 0);
446 layout_vb = gtk_vbox_new(FALSE, 5);
447 gtk_container_set_border_width(GTK_CONTAINER(layout_vb), 10);
448 gtk_box_pack_start(GTK_BOX(topic_vb), layout_vb, FALSE, FALSE, 0);
450 /* colorize vbox (we need an event box for this!) */
451 topic_eb = gtk_event_box_new();
452 gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb);
453 #if GTK_CHECK_VERSION(3,0,0)
454 gtk_widget_override_background_color(topic_eb, GTK_STATE_NORMAL, &rgba_topic_content_bg);
456 gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &topic_content_bg);
458 *to_fill = layout_vb;
464 /* a file link was pressed */
466 welcome_filename_link_press_cb(GtkWidget *widget _U_, GdkEventButton *event _U_, gpointer data)
468 menu_open_filename(data);
473 typedef struct _recent_item_status {
481 } recent_item_status;
484 * Fetch the status of a file.
485 * This function might be called as a thread. We can't use any drawing
486 * routines here: http://developer.gnome.org/gdk/2.24/gdk-Threads.html
488 static void *get_recent_item_status(void *data)
490 recent_item_status *ri_stat = (recent_item_status *) data;
499 * Add file size. We use binary prefixes instead of IEC because that's what
502 err = ws_stat64(ri_stat->filename, &stat_buf);
504 g_mutex_lock(recent_mtx);
508 if (stat_buf.st_size/1024/1024/1024 > 10) {
509 g_string_append_printf(ri_stat->str, " (%" G_GINT64_MODIFIER "d GB)", (gint64) (stat_buf.st_size/1024/1024/1024));
510 } else if (stat_buf.st_size/1024/1024 > 10) {
511 g_string_append_printf(ri_stat->str, " (%" G_GINT64_MODIFIER "d MB)", (gint64) (stat_buf.st_size/1024/1024));
512 } else if (stat_buf.st_size/1024 > 10) {
513 g_string_append_printf(ri_stat->str, " (%" G_GINT64_MODIFIER "d KB)", (gint64) (stat_buf.st_size/1024));
515 g_string_append_printf(ri_stat->str, " (%" G_GINT64_MODIFIER "d Bytes)", (gint64) (stat_buf.st_size));
517 /* pango format string */
518 g_string_prepend(ri_stat->str, "<span foreground='blue'>");
519 g_string_append(ri_stat->str, "</span>");
521 g_string_append(ri_stat->str, " [not found]");
524 if (!ri_stat->label) { /* The widget went away while we were busy. */
525 g_free(ri_stat->filename);
526 g_string_free(ri_stat->str, TRUE);
529 ri_stat->stat_done = TRUE;
532 g_mutex_unlock(recent_mtx);
538 /* Timeout callback for recent items */
540 update_recent_items(gpointer data)
542 recent_item_status *ri_stat = (recent_item_status *) data;
543 gboolean again = TRUE;
550 g_mutex_lock(recent_mtx);
552 if (ri_stat->stat_done) {
554 gtk_label_set_markup(GTK_LABEL(ri_stat->label), ri_stat->str->str);
555 if (ri_stat->err == 0) {
556 gtk_widget_set_sensitive(ri_stat->label, TRUE);
557 #ifdef MAIN_MENU_USE_UIMANAGER
558 gtk_action_set_sensitive((GtkAction *) ri_stat->menu_item, TRUE);
560 gtk_widget_set_sensitive(GTK_WIDGET(ri_stat->menu_item), TRUE);
565 /* Else append some sort of Unicode or ASCII animation to the label? */
567 g_mutex_unlock(recent_mtx);
572 static void welcome_filename_destroy_cb(GtkWidget *w _U_, gpointer data) {
573 recent_item_status *ri_stat = (recent_item_status *) data;
580 g_mutex_lock(recent_mtx);
582 if (ri_stat->timer) {
583 g_source_remove(ri_stat->timer);
587 g_object_unref(ri_stat->menu_item);
589 if (ri_stat->stat_done) {
590 g_free(ri_stat->filename);
591 g_string_free(ri_stat->str, TRUE);
594 ri_stat->label = NULL;
597 g_mutex_unlock(recent_mtx);
601 /* create a "file link widget" */
603 welcome_filename_link_new(const gchar *filename, GtkWidget **label, GObject *menu_item)
610 gsize uni_start, uni_end;
611 const glong max = 60;
612 recent_item_status *ri_stat;
615 str = g_string_new(filename);
616 uni_len = g_utf8_strlen(str->str, str->len);
618 /* cut max filename length */
620 uni_start = g_utf8_offset_to_pointer(str->str, 20) - str->str;
621 uni_end = g_utf8_offset_to_pointer(str->str, uni_len - max) - str->str;
622 g_string_erase(str, uni_start, uni_end);
623 g_string_insert(str, uni_start, " " UTF8_HORIZONTAL_ELLIPSIS " ");
626 /* escape the possibly shortened filename before adding pango language */
627 str_escaped=g_markup_escape_text(str->str, -1);
628 g_string_free(str, TRUE);
631 w = gtk_label_new(str_escaped);
633 gtk_misc_set_padding(GTK_MISC(w), 5, 2);
634 gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.0f);
635 gtk_widget_set_sensitive(w, FALSE);
637 ri_stat = g_malloc(sizeof(recent_item_status));
638 ri_stat->filename = g_strdup(filename);
640 ri_stat->menu_item = menu_item;
641 ri_stat->str = g_string_new(str_escaped);
642 ri_stat->stat_done = FALSE;
644 g_object_ref(G_OBJECT(menu_item));
645 g_signal_connect(w, "destroy", G_CALLBACK(welcome_filename_destroy_cb), ri_stat);
649 g_thread_create(get_recent_item_status, ri_stat, FALSE, NULL);
650 ri_stat->timer = g_timeout_add(200, update_recent_items, ri_stat);
652 get_recent_item_status(ri_stat);
653 update_recent_items(ri_stat);
657 eb = gtk_event_box_new();
658 #if GTK_CHECK_VERSION(3,0,0)
659 gtk_widget_override_background_color(eb, GTK_STATE_NORMAL, &rgba_topic_item_idle_bg);
661 gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
663 gtk_container_add(GTK_CONTAINER(eb), w);
664 gtk_widget_set_tooltip_text(eb, filename);
666 g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), w);
667 g_signal_connect(eb, "leave-notify-event", G_CALLBACK(welcome_item_leave_cb), w);
668 g_signal_connect(eb, "button-press-event", G_CALLBACK(welcome_filename_link_press_cb), (gchar *) filename);
674 /* reset the list of recent files */
676 main_welcome_reset_recent_capture_files(void)
678 GtkWidget *child_box;
680 GList* child_list_item;
683 if(welcome_file_panel_vb) {
684 child_box = scroll_box_dynamic_reset(welcome_file_panel_vb);
685 child_list = gtk_container_get_children(GTK_CONTAINER(child_box));
686 child_list_item = child_list;
688 while(child_list_item) {
689 gtk_container_remove(GTK_CONTAINER(child_box), child_list_item->data);
690 child_list_item = g_list_next(child_list_item);
693 g_list_free(child_list);
698 /* add a new file to the list of recent files */
700 main_welcome_add_recent_capture_file(const char *widget_cf_name, GObject *menu_item)
703 GtkWidget *child_box;
707 w = welcome_filename_link_new(widget_cf_name, &label, menu_item);
708 child_box = scroll_box_dynamic_add(welcome_file_panel_vb);
709 gtk_box_pack_start(GTK_BOX(child_box), w, FALSE, FALSE, 0);
710 gtk_widget_show_all(w);
711 gtk_widget_show_all(child_box);
715 static gboolean select_current_ifaces(GtkTreeModel *model,
722 gboolean found = FALSE;
724 GtkTreeSelection *selection = (GtkTreeSelection *)userdata;
725 gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1);
726 for (i = 0; i < global_capture_opts.ifaces->len; i++) {
727 if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, if_name) == 0) {
728 if (!gtk_tree_selection_path_is_selected(selection, path)) {
729 gtk_tree_selection_select_iter(selection, iter);
736 gtk_tree_selection_unselect_iter(selection, iter);
741 gboolean on_selection_changed(GtkTreeSelection *selection _U_,
744 gboolean path_currently_selected,
749 interface_options interface_opts;
751 cap_settings_t cap_settings;
752 gboolean found = FALSE;
753 displayed_interface d_interface;
755 d_interface.name = NULL;
756 d_interface.descr = NULL;
757 gtk_tree_model_get_iter (model, &iter, path);
758 gtk_tree_model_get (model, &iter, IFACE_NAME, &if_name, -1);
759 if (global_capture_opts.ifaces->len > 0) {
760 for (i = 0; i < global_capture_opts.ifaces->len; i++) {
761 if (strcmp(g_array_index(global_capture_opts.ifaces, interface_options, i).name, if_name) == 0) {
763 if (path_currently_selected) {
764 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, i);
765 global_capture_opts.ifaces = g_array_remove_index(global_capture_opts.ifaces, i);
766 if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && interfaces_dialog_window_present()) {
767 update_selected_interface(g_strdup(interface_opts.name), FALSE);
769 if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && dlg_window_present()) {
770 enable_selected_interface(interface_opts.name, FALSE);
772 g_free(interface_opts.name);
773 g_free(interface_opts.descr);
774 g_free(interface_opts.cfilter);
775 #ifdef HAVE_PCAP_REMOTE
776 g_free(interface_opts.remote_host);
777 g_free(interface_opts.remote_port);
778 g_free(interface_opts.auth_username);
779 g_free(interface_opts.auth_password);
786 if (!found && !path_currently_selected) {
787 for (j = 0; j < interfaces->len; j++) {
788 d_interface = g_array_index(interfaces, displayed_interface, j);
789 if (strcmp(d_interface.name, if_name) == 0) {
790 interface_opts.name = g_strdup(d_interface.name);
791 interface_opts.descr = g_strdup(d_interface.descr);
792 interface_opts.linktype = capture_dev_user_linktype_find(interface_opts.name);
793 interface_opts.cfilter = g_strdup(global_capture_opts.default_options.cfilter);
794 interface_opts.has_snaplen = global_capture_opts.default_options.has_snaplen;
795 interface_opts.snaplen = global_capture_opts.default_options.snaplen;
796 cap_settings = capture_get_cap_settings (interface_opts.name);;
797 interface_opts.promisc_mode = global_capture_opts.default_options.promisc_mode;
798 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
799 interface_opts.buffer_size = global_capture_opts.default_options.buffer_size;
801 interface_opts.monitor_mode = cap_settings.monitor_mode;
802 #ifdef HAVE_PCAP_REMOTE
803 if (d_interface.remote_opts.src_type == CAPTURE_IFREMOTE) {
804 interface_opts.src_type = d_interface.remote_opts.src_type;
805 interface_opts.remote_host = g_strdup(d_interface.remote_opts.remote_host_opts.remote_host);
806 interface_opts.remote_port = g_strdup(d_interface.remote_opts.remote_host_opts.remote_port);
807 interface_opts.auth_type = d_interface.remote_opts.remote_host_opts.auth_type;
808 interface_opts.auth_username = g_strdup(d_interface.remote_opts.remote_host_opts.auth_username);
809 interface_opts.auth_password = g_strdup(d_interface.remote_opts.remote_host_opts.auth_password);
810 interface_opts.datatx_udp = d_interface.remote_opts.remote_host_opts.datatx_udp;
811 interface_opts.nocap_rpcap = d_interface.remote_opts.remote_host_opts.nocap_rpcap;
812 interface_opts.nocap_local = d_interface.remote_opts.remote_host_opts.nocap_local;
813 #ifdef HAVE_PCAP_SETSAMPLING
814 interface_opts.sampling_method = d_interface.remote_opts.sampling_method;
815 interface_opts.sampling_param = d_interface.remote_opts.sampling_param;
818 interface_opts.src_type = global_capture_opts.default_options.src_type;
819 interface_opts.remote_host = g_strdup(global_capture_opts.default_options.remote_host);
820 interface_opts.remote_port = g_strdup(global_capture_opts.default_options.remote_port);
821 interface_opts.auth_type = global_capture_opts.default_options.auth_type;
822 interface_opts.auth_username = g_strdup(global_capture_opts.default_options.auth_username);
823 interface_opts.auth_password = g_strdup(global_capture_opts.default_options.auth_password);
824 interface_opts.datatx_udp = global_capture_opts.default_options.datatx_udp;
825 interface_opts.nocap_rpcap = global_capture_opts.default_options.nocap_rpcap;
826 interface_opts.nocap_local = global_capture_opts.default_options.nocap_local;
827 #ifdef HAVE_PCAP_SETSAMPLING
828 interface_opts.sampling_method = global_capture_opts.default_options.sampling_method;
829 interface_opts.sampling_param = global_capture_opts.default_options.sampling_param;
834 g_array_append_val(global_capture_opts.ifaces, interface_opts);
835 if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && interfaces_dialog_window_present()) {
836 update_selected_interface(g_strdup(interface_opts.name), TRUE);
838 if (gtk_widget_is_focus(g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES)) && dlg_window_present()) {
839 enable_selected_interface(interface_opts.name, TRUE);
848 static gboolean activate_ifaces(GtkTreeModel *model,
849 GtkTreePath *path _U_,
855 GtkTreeSelection *selection;
856 selected_name_t *entry = (selected_name_t *)userdata;
858 view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
859 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
860 gtk_tree_model_get (model, iter, IFACE_NAME, &if_name, -1);
861 if (strcmp(if_name, entry->name) == 0) {
862 if (entry->activate) {
863 gtk_tree_selection_select_iter(selection, iter);
865 gtk_tree_selection_unselect_iter(selection, iter);
872 void change_interface_selection(gchar* name, gboolean activate)
876 selected_name_t entry;
878 view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
879 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
880 entry.name = g_strdup(name);
881 entry.activate = activate;
882 gtk_tree_model_foreach(GTK_TREE_MODEL(model), (GtkTreeModelForeachFunc)(activate_ifaces), (gpointer) &entry);
885 void change_selection_for_all(gboolean enable)
890 for (i = 0; i < interfaces->len; i++) {
891 change_interface_selection(g_array_index(interfaces, displayed_interface, i).name, enable);
903 GtkTreeSelection *entry;
905 if (global_capture_opts.ifaces->len > 0 && swindow) {
906 view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
907 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
908 entry = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
909 gtk_tree_model_foreach(GTK_TREE_MODEL(model), select_current_ifaces, (gpointer) entry);
910 gtk_widget_grab_focus(view);
915 #ifdef HAVE_PCAP_REMOTE
917 add_interface_to_list(gchar *name, gchar *descr, remote_options *remote_opts)
919 GtkWidget *view, *icon;
924 displayed_interface d_interface;
926 d_interface.name = g_strdup(name);
927 d_interface.descr = g_strdup(descr);
928 d_interface.remote_opts.src_type = remote_opts->src_type;
929 d_interface.remote_opts.remote_host_opts.remote_host = g_strdup(remote_opts->remote_host_opts.remote_host);
930 d_interface.remote_opts.remote_host_opts.remote_port = g_strdup(remote_opts->remote_host_opts.remote_port);
931 d_interface.remote_opts.remote_host_opts.auth_type = remote_opts->remote_host_opts.auth_type;
932 d_interface.remote_opts.remote_host_opts.auth_username = g_strdup(remote_opts->remote_host_opts.auth_username);
933 d_interface.remote_opts.remote_host_opts.auth_password = g_strdup(remote_opts->remote_host_opts.auth_password);
934 d_interface.remote_opts.remote_host_opts.datatx_udp = remote_opts->remote_host_opts.datatx_udp;
935 d_interface.remote_opts.remote_host_opts.nocap_rpcap = remote_opts->remote_host_opts.nocap_rpcap;
936 d_interface.remote_opts.remote_host_opts.nocap_local = remote_opts->remote_host_opts.nocap_local;
937 #ifdef HAVE_PCAP_SETSAMPLING
938 d_interface.remote_opts.sampling_method = remote_opts->sampling_method;
939 d_interface.remote_opts.sampling_param = remote_opts->sampling_param;
941 icon = xpm_to_widget(capture_airpcap_16_xpm);
942 d_interface.icon = icon;
943 view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
944 model = gtk_tree_view_get_model(GTK_TREE_VIEW(view));
945 size = gtk_tree_model_iter_n_children(model, NULL);
946 lines = g_strdup_printf("%d", size-1);
947 g_array_append_val(interfaces, d_interface);
948 if (gtk_tree_model_get_iter_from_string(model, &iter, lines)) {
949 gtk_list_store_append (GTK_LIST_STORE(model), &iter);
950 gtk_list_store_set(GTK_LIST_STORE(model), &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, descr, IFACE_NAME, name, -1);
955 /* list the interfaces */
957 welcome_if_tree_load(void)
964 gchar *err_str = NULL;
967 GtkListStore *store = NULL;
969 GtkWidget *icon, *view;
970 GtkTreeSelection *entry;
971 displayed_interface d_interface;
973 view = g_object_get_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES);
974 entry = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
975 gtk_tree_selection_unselect_all(entry);
976 store = gtk_list_store_new(NUMCOLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
978 /* LOAD THE INTERFACES */
979 if (interfaces && interfaces->len > 0) {
980 for (i = 0; i < interfaces->len; i++) {
981 d_interface = g_array_index(interfaces, displayed_interface, i);
982 gtk_list_store_append (store, &iter);
983 gtk_list_store_set (store, &iter, ICON, d_interface.icon, IFACE_DESCR, d_interface.descr, IFACE_NAME, d_interface.name, -1);
986 interfaces = g_array_new(TRUE, TRUE, sizeof(displayed_interface));
987 if_list = capture_interface_list(&err, &err_str);
988 if_list = g_list_sort (if_list, if_list_comparator_alph);
989 if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
990 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
993 } else if (err_str) {
996 if (g_list_length(if_list) > 0) {
997 /* List the interfaces */
998 for (curr = g_list_first(if_list); curr; curr = g_list_next(curr)) {
999 if_info = curr->data;
1000 /* Continue if capture device is hidden */
1001 if (prefs_is_capture_device_hidden(if_info->name)) {
1004 gtk_list_store_append (store, &iter);
1005 d_interface.name = g_strdup(if_info->name);
1006 #ifdef HAVE_PCAP_REMOTE
1007 d_interface.remote_opts.src_type = CAPTURE_IFLOCAL;
1010 if (get_airpcap_if_from_name(airpcap_if_list,if_info->name) != NULL)
1011 icon = xpm_to_widget(capture_airpcap_16_xpm);
1013 icon = capture_get_if_icon(if_info);
1015 icon = capture_get_if_icon(if_info);
1017 d_interface.icon = icon;
1018 user_descr = capture_dev_user_descr_find(if_info->name);
1021 gchar *comment = user_descr;
1022 user_descr = g_strdup_printf("%s (%s)", comment, if_info->name);
1025 gtk_list_store_set(store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, user_descr, IFACE_NAME, if_info->name, -1);
1026 d_interface.descr = g_strdup(user_descr);
1027 g_free (user_descr);
1028 } else if (if_info->description) {
1029 gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, if_info->description, IFACE_NAME, if_info->name, -1);
1030 d_interface.descr = g_strdup(if_info->description);
1032 gtk_list_store_set (store, &iter, ICON, gtk_image_get_pixbuf(GTK_IMAGE(icon)), IFACE_DESCR, if_info->name, IFACE_NAME, if_info->name, -1);
1033 d_interface.descr = g_strdup(if_info->name);
1035 g_array_append_val(interfaces, d_interface);
1038 free_interface_list(if_list);
1039 gtk_tree_view_set_model(GTK_TREE_VIEW(if_view), GTK_TREE_MODEL (store));
1040 if (global_capture_opts.ifaces->len > 0) {
1041 gtk_tree_model_foreach(GTK_TREE_MODEL(store), select_current_ifaces, (gpointer) entry);
1042 gtk_widget_grab_focus(view);
1044 gtk_tree_selection_set_select_function(entry, on_selection_changed, NULL, NULL);
1046 #endif /* HAVE_LIBPCAP */
1050 /* reload the list of interfaces */
1052 welcome_if_panel_reload(void)
1055 GtkWidget *child_box;
1057 GList* child_list_item;
1059 if(welcome_if_panel_vb) {
1060 child_box = scroll_box_dynamic_reset(welcome_if_panel_vb);
1061 child_list = gtk_container_get_children(GTK_CONTAINER(child_box));
1062 child_list_item = child_list;
1064 while(child_list_item) {
1065 gtk_container_remove(GTK_CONTAINER(child_box), child_list_item->data);
1066 child_list_item = g_list_next(child_list_item);
1069 g_list_free(child_list);
1070 welcome_if_tree_load();
1071 gtk_widget_show_all(welcome_if_panel_vb);
1073 #endif /* HAVE_LIBPCAP */
1077 static void capture_if_start(GtkWidget *w _U_, gpointer data _U_)
1080 interface_options interface_opts;
1083 if (global_capture_opts.ifaces->len == 0) {
1084 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1085 "You didn't specify an interface on which to capture packets.");
1089 if (global_capture_opts.ifaces->len > 1) {
1090 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1091 "You specified multiple interfaces for capturing which this version of Wireshark doesn't support.");
1096 /* XXX - remove this? */
1097 if (global_capture_opts.save_file) {
1098 g_free(global_capture_opts.save_file);
1099 global_capture_opts.save_file = NULL;
1102 interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, 0);
1103 airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, interface_opts.name);
1104 airpcap_if_selected = airpcap_if_active;
1105 airpcap_set_toolbar_start_capture(airpcap_if_active);
1107 capture_start_cb(NULL, NULL);
1111 /* create the welcome page */
1115 GtkWidget *welcome_scrollw;
1116 GtkWidget *welcome_eb;
1117 GtkWidget *welcome_vb;
1118 GtkWidget *column_vb;
1122 GtkWidget *topic_vb;
1123 GtkWidget *topic_to_fill;
1124 GtkWidget *file_child_box;
1128 DWORD chimney_enabled = 0;
1129 DWORD ce_size = sizeof(chimney_enabled);
1132 GtkTreeSelection *selection;
1133 GtkCellRenderer *renderer;
1134 GtkTreeViewColumn *column;
1137 gchar *err_str = NULL;
1140 /* prepare colors */
1142 /* Allocating collor isn't necessary? */
1144 /* "page" background */
1145 get_color(&welcome_bg);
1147 /* header bar background color */
1148 get_color(&header_bar_bg);
1150 /* topic header background color */
1151 get_color(&topic_header_bg);
1153 /* topic content background color */
1154 get_color(&topic_content_bg);
1156 #if GTK_CHECK_VERSION(3,0,0)
1157 rgba_topic_item_idle_bg = rgba_topic_content_bg;
1159 topic_item_idle_bg = topic_content_bg;
1162 /* Allocating collor isn't necessary? */
1163 /* topic item entered color */
1164 get_color(&topic_item_entered_bg);
1166 welcome_scrollw = scrolled_window_new(NULL, NULL);
1168 welcome_vb = gtk_vbox_new(FALSE, 0);
1170 welcome_eb = gtk_event_box_new();
1171 gtk_container_add(GTK_CONTAINER(welcome_eb), welcome_vb);
1172 #if GTK_CHECK_VERSION(3,0,0)
1173 gtk_widget_override_background_color(welcome_eb, GTK_STATE_NORMAL, &rgba_welcome_bg);
1175 gtk_widget_modify_bg(welcome_eb, GTK_STATE_NORMAL, &welcome_bg);
1178 header = welcome_header_new();
1179 gtk_box_pack_start(GTK_BOX(welcome_vb), header, FALSE, FALSE, 0);
1182 welcome_hb = gtk_hbox_new(FALSE, 10);
1183 gtk_container_set_border_width(GTK_CONTAINER(welcome_hb), 10);
1184 gtk_box_pack_start(GTK_BOX(welcome_vb), welcome_hb, TRUE, TRUE, 0);
1187 /* column capture */
1188 column_vb = gtk_vbox_new(FALSE, 10);
1189 #if GTK_CHECK_VERSION(3,0,0)
1190 gtk_widget_override_background_color(column_vb, GTK_STATE_NORMAL, &rgba_welcome_bg);
1192 gtk_widget_modify_bg(column_vb, GTK_STATE_NORMAL, &welcome_bg);
1194 gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
1197 topic_vb = welcome_topic_new("Capture", &topic_to_fill);
1198 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
1201 if_list = capture_interface_list(&err, &err_str);
1202 if (g_list_length(if_list) > 0) {
1203 item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_INTERFACES,
1205 "Live list of the capture interfaces\n(counts incoming packets)",
1206 "Same as Capture/Interfaces menu or toolbar item",
1207 welcome_button_callback_helper, capture_if_cb);
1208 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1210 swindow = gtk_scrolled_window_new (NULL, NULL);
1211 gtk_widget_set_size_request(swindow, FALSE, 100);
1212 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(swindow), GTK_SHADOW_IN);
1213 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1215 if_view = gtk_tree_view_new ();
1216 g_object_set(G_OBJECT(if_view), "headers-visible", FALSE, NULL);
1217 g_object_set_data(G_OBJECT(welcome_hb), TREE_VIEW_INTERFACES, if_view);
1218 renderer = gtk_cell_renderer_pixbuf_new();
1219 column = gtk_tree_view_column_new_with_attributes ("",
1220 GTK_CELL_RENDERER(renderer),
1223 gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column);
1224 renderer = gtk_cell_renderer_text_new();
1225 column = gtk_tree_view_column_new_with_attributes ("",
1226 GTK_CELL_RENDERER(renderer),
1227 "text", IFACE_DESCR,
1229 gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column);
1230 gtk_tree_view_column_set_resizable(gtk_tree_view_get_column(GTK_TREE_VIEW(if_view), 0), TRUE);
1231 renderer = gtk_cell_renderer_text_new();
1232 column = gtk_tree_view_column_new_with_attributes ("",
1233 GTK_CELL_RENDERER(renderer),
1236 gtk_tree_view_append_column(GTK_TREE_VIEW(if_view), column);
1237 gtk_tree_view_column_set_visible(column, FALSE);
1238 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(if_view));
1239 gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
1241 item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_START,
1243 "Choose one or more interfaces to capture from, then <b>Start</b>",
1244 "Same as Capture/Interfaces with default options",
1245 (welcome_button_callback_t)capture_if_start, (gpointer)if_view);
1247 item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_START,
1249 "Choose exactly one interface to capture from, then <b>Start</b>",
1250 "Same as Capture/Interfaces with default options",
1251 (welcome_button_callback_t)capture_if_start, (gpointer)if_view);
1253 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1254 welcome_if_tree_load();
1255 gtk_container_add (GTK_CONTAINER (swindow), if_view);
1256 gtk_container_add(GTK_CONTAINER(topic_to_fill), swindow);
1258 item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_OPTIONS,
1260 "Start a capture with detailed options",
1261 "Same as Capture/Options menu or toolbar item",
1262 welcome_button_callback_helper, capture_prep_cb);
1263 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1265 /* Check for chimney offloading */
1266 reg_ret = RegQueryValueEx(HKEY_LOCAL_MACHINE,
1267 _T("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\EnableTCPChimney"),
1268 NULL, NULL, (LPBYTE) &chimney_enabled, &ce_size);
1269 if (reg_ret == ERROR_SUCCESS && chimney_enabled) {
1270 item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
1271 "Offloading Detected",
1272 "TCP Chimney offloading is enabled. You \nmight not capture much data.",
1273 topic_online_url(ONLINEPAGE_CHIMNEY),
1274 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_CHIMNEY));
1275 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1279 label_text = g_strdup("No interface can be used for capturing in\n"
1280 "this system with the current configuration.\n\n"
1281 "See Capture Help below for details.");
1282 w = gtk_label_new(label_text);
1283 gtk_label_set_markup(GTK_LABEL(w), label_text);
1284 g_free (label_text);
1285 gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.0f);
1286 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
1289 free_interface_list(if_list);
1291 /* capture help topic */
1292 topic_vb = welcome_topic_new("Capture Help", &topic_to_fill);
1293 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
1295 item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
1297 "Step by step to a successful capture setup",
1298 topic_online_url(ONLINEPAGE_CAPTURE_SETUP),
1299 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_CAPTURE_SETUP));
1300 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1302 item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
1304 "Specific information for capturing on:\nEthernet, WLAN, ...",
1305 topic_online_url(ONLINEPAGE_NETWORK_MEDIA),
1306 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_NETWORK_MEDIA));
1307 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1309 label_text = g_strdup("<span foreground=\"black\">Capturing is not compiled into\nthis version of Wireshark!</span>");
1310 w = gtk_label_new(label_text);
1311 gtk_label_set_markup(GTK_LABEL(w), label_text);
1312 g_free (label_text);
1313 gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.0f);
1314 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
1315 #endif /* HAVE_LIBPCAP */
1317 /* fill bottom space */
1318 w = gtk_label_new("");
1319 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
1323 topic_vb = welcome_topic_new("Files", &topic_to_fill);
1324 gtk_box_pack_start(GTK_BOX(welcome_hb), topic_vb, TRUE, TRUE, 0);
1326 item_hb = welcome_button(GTK_STOCK_OPEN,
1328 "Open a previously captured file",
1329 "Same as File/Open menu or toolbar item",
1330 welcome_button_callback_helper, file_open_cmd_cb);
1331 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1333 /* prepare list of recent files (will be filled in later) */
1334 label_text = g_strdup("<span foreground=\"black\">Open Recent:</span>");
1335 w = gtk_label_new(label_text);
1336 gtk_label_set_markup(GTK_LABEL(w), label_text);
1337 g_free (label_text);
1338 gtk_misc_set_alignment (GTK_MISC(w), 0.0f, 0.0f);
1339 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
1341 file_child_box = gtk_vbox_new(FALSE, 1);
1342 /* 17 file items or 300 pixels height is about the size */
1343 /* that still fits on a screen of about 1000*700 */
1344 welcome_file_panel_vb = scroll_box_dynamic_new(GTK_WIDGET(file_child_box), 17, 300);
1345 gtk_box_pack_start(GTK_BOX(topic_to_fill), welcome_file_panel_vb, FALSE, FALSE, 0);
1347 item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
1349 "A rich assortment of example capture files on the wiki",
1350 topic_online_url(ONLINEPAGE_SAMPLE_CAPTURES),
1351 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_SAMPLE_CAPTURES));
1352 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1354 /* fill bottom space */
1355 w = gtk_label_new("");
1356 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
1360 column_vb = gtk_vbox_new(FALSE, 10);
1361 gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
1364 topic_vb = welcome_topic_new("Online", &topic_to_fill);
1365 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
1367 item_hb = welcome_button(GTK_STOCK_HOME,
1369 "Visit the project's website",
1370 topic_online_url(ONLINEPAGE_HOME),
1371 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_HOME));
1372 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1375 item_hb = welcome_button(GTK_STOCK_HELP,
1378 "(local version, if installed)",
1379 "Locally installed (if installed) otherwise online version",
1380 topic_menu_cb, GINT_TO_POINTER(HELP_CONTENT));
1382 item_hb = welcome_button(GTK_STOCK_HELP,
1386 topic_online_url(ONLINEPAGE_USERGUIDE),
1387 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
1389 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1391 item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
1393 "Work with Wireshark as securely as possible",
1394 topic_online_url(ONLINEPAGE_SECURITY),
1395 topic_menu_cb, GINT_TO_POINTER(ONLINEPAGE_SECURITY));
1396 gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
1399 /* XXX - add this, once the Windows update functionality is implemented */
1401 topic_vb = welcome_topic_new("Updates", &topic_to_fill);
1402 gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
1404 label_text = g_strdup("<span foreground=\"black\">No updates available!</span>");
1405 w = gtk_label_new(label_text);
1406 gtk_label_set_markup(GTK_LABEL(w), label_text);
1407 g_free (label_text);
1408 gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
1413 gtk_widget_show_all(welcome_eb);
1415 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
1417 gtk_widget_show_all(welcome_scrollw);
1420 recent_mtx = g_mutex_new();
1423 return welcome_scrollw;
1426 GtkWidget* get_welcome_window(void)