Trivial warning fixes
[obnox/wireshark/wip.git] / gtk / main_welcome.c
1 /* main_welcome.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 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
27
28 #ifdef HAVE_SYS_TYPES_H
29 #include <sys/types.h>
30 #endif
31 #include <time.h>
32
33 #include <gtk/gtk.h>
34
35 #include <epan/prefs.h>
36
37 #include "../color.h"
38 #include "capture.h"
39 #include "capture-pcap-util.h"
40 #include "capture_opts.h"
41 #include "capture_ui_utils.h"
42 #include "simple_dialog.h"
43 #include <wsutil/file_util.h>
44
45 #include "gtk/gui_utils.h"
46 #include "gtk/color_utils.h"
47 #include "gtk/recent.h"
48 #include "gtk/gtkglobals.h"
49 #include "gtk/main.h"
50 #include "gtk/main_menu.h"
51 #include "gtk/main_welcome.h"
52 #include "gtk/capture_dlg.h"
53 #include "gtk/capture_file_dlg.h"
54 #include "gtk/help_dlg.h"
55 #include "gtk/stock_icons.h"
56 #include "gtk/capture_globals.h"
57 #include "../image/wssplash-dev.xpm"
58 #include "../version_info.h"
59
60 #ifdef HAVE_AIRPCAP
61 #include "airpcap.h"
62 #include "airpcap_loader.h"
63 #include "airpcap_gui_utils.h"
64 #endif
65
66 /* XXX */
67 extern gint if_list_comparator_alph (const void *first_arg, const void *second_arg);
68
69
70 static GdkColor header_bar_bg;
71 static GdkColor topic_header_bg;
72 static GdkColor topic_content_bg;
73 static GdkColor topic_item_idle_bg;
74 static GdkColor topic_item_entered_bg;
75
76 static GtkWidget *welcome_file_panel_vb = NULL;
77 #ifdef HAVE_LIBPCAP
78 static GtkWidget *welcome_if_panel_vb = NULL;
79 #endif
80
81
82 /* The "scroll box dynamic" is a (complicated) pseudo widget to */
83 /* place a vertically list of widgets in (currently the interfaces and recent files). */
84 /* Once this list get's higher than a specified amount, */
85 /* it is moved into a scrolled_window. */
86 /* This is all complicated, the scrolled window is a bit ugly, */
87 /* the sizes might not be the same on all systems, ... */
88 /* ... but that's the best what we currently have */
89 #define SCROLL_BOX_CHILD_BOX        "ScrollBoxDynamic_ChildBox"
90 #define SCROLL_BOX_MAX_CHILDS       "ScrollBoxDynamic_MaxChilds"
91 #define SCROLL_BOX_SCROLLW_Y_SIZE   "ScrollBoxDynamic_Scrollw_Y_Size"
92 #define SCROLL_BOX_SCROLLW          "ScrollBoxDynamic_Scrollw"
93
94
95 static GtkWidget *
96 scroll_box_dynamic_new(GtkBox *child_box, guint max_childs, guint scrollw_y_size) {
97     GtkWidget * parent_box;
98
99
100     parent_box = gtk_vbox_new(FALSE, 0);
101     gtk_box_pack_start(GTK_BOX(parent_box), GTK_WIDGET(child_box), TRUE, TRUE, 0);
102     g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_CHILD_BOX, child_box);
103     g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_MAX_CHILDS, GINT_TO_POINTER(max_childs));
104     g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW_Y_SIZE, GINT_TO_POINTER(scrollw_y_size));
105     gtk_widget_show_all(parent_box);
106
107     return parent_box;
108 }
109
110 static GtkWidget *
111 scroll_box_dynamic_add(GtkWidget *parent_box)
112 {
113     GtkWidget *child_box;
114     GtkWidget *scrollw;
115     guint max_cnt;
116     guint curr_cnt;
117     guint scrollw_y_size;
118     GList *childs;
119
120
121     child_box = g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_CHILD_BOX);
122     max_cnt = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_MAX_CHILDS));
123
124     /* get the current number of children */
125     childs = gtk_container_get_children(GTK_CONTAINER(child_box));
126     curr_cnt = g_list_length(childs);
127     g_list_free(childs);
128
129     /* have we just reached the max? */
130     if(curr_cnt == max_cnt) {
131         /* create the scrolled window */
132         /* XXX - there's no way to get rid of the shadow frame - except for creating an own widget :-( */
133         scrollw = scrolled_window_new(NULL, NULL);
134         scrollw_y_size = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW_Y_SIZE));
135             gtk_widget_set_usize(scrollw, -1, scrollw_y_size);
136
137         g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW, scrollw);
138         gtk_box_pack_start(GTK_BOX(parent_box), scrollw, TRUE, TRUE, 0);
139
140         /* move child_box from parent_box into scrolled window */
141         gtk_widget_ref(child_box);
142         gtk_container_remove(GTK_CONTAINER(parent_box), child_box);
143         gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrollw),
144                                               child_box);
145         gtk_widget_show_all(scrollw);
146     }
147
148     return child_box;
149 }
150
151 static GtkWidget *
152 scroll_box_dynamic_reset(GtkWidget *parent_box)
153 {
154     GtkWidget *child_box, *scrollw;
155
156
157     child_box = g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_CHILD_BOX);
158     scrollw = g_object_get_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW);
159
160     if(scrollw != NULL) {
161         /* move the child_box back from scrolled window into the parent_box */
162         gtk_widget_ref(child_box);
163         gtk_container_remove(GTK_CONTAINER(parent_box), scrollw);
164         g_object_set_data(G_OBJECT(parent_box), SCROLL_BOX_SCROLLW, NULL);
165         gtk_box_pack_start(GTK_BOX(parent_box), child_box, TRUE, TRUE, 0);
166     }
167
168     return child_box;
169 }
170
171
172
173
174 /* mouse entered this widget - change background color */
175 static gboolean
176 welcome_item_enter_cb(GtkWidget *eb, GdkEventCrossing *event _U_, gpointer user_data _U_)
177 {
178     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_entered_bg);
179
180     return FALSE;
181 }
182
183 /* mouse has left this widget - change background color  */
184 static gboolean
185 welcome_item_leave_cb(GtkWidget *eb, GdkEvent *event _U_, gpointer user_data _U_)
186 {
187     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
188
189     return FALSE;
190 }
191
192
193 /* create a "button widget" */
194 static GtkWidget *
195 welcome_button(const gchar *stock_item,
196                const gchar * title, const gchar * subtitle, const gchar *tooltip,
197                            GtkSignalFunc callback, void *callback_data)
198 {
199     GtkWidget *eb, *w, *item_hb, *text_vb;
200     gchar *formatted_text;
201     GtkTooltips *tooltips;
202
203
204     tooltips = gtk_tooltips_new();
205
206     item_hb = gtk_hbox_new(FALSE, 1);
207
208     /* event box (for background color and events) */
209     eb = gtk_event_box_new();
210     gtk_container_add(GTK_CONTAINER(eb), item_hb);
211     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
212     if(tooltip != NULL) {
213         gtk_tooltips_set_tip(tooltips, eb, tooltip, "");
214     }
215
216     g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), NULL);
217     g_signal_connect(eb, "leave-notify-event", G_CALLBACK(welcome_item_leave_cb), NULL);
218     g_signal_connect(eb, "button-press-event", G_CALLBACK(callback), callback_data);
219
220     /* icon */
221     w = gtk_image_new_from_stock(stock_item, GTK_ICON_SIZE_LARGE_TOOLBAR);
222     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 5);
223
224     text_vb = gtk_vbox_new(FALSE, 3);
225
226     /* title */
227     w = gtk_label_new(title);
228     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
229     formatted_text = g_strdup_printf("<span weight=\"bold\" size=\"x-large\" foreground=\"black\">%s</span>", title);
230     gtk_label_set_markup(GTK_LABEL(w), formatted_text);
231     g_free(formatted_text);
232     gtk_box_pack_start(GTK_BOX(text_vb), w, FALSE, FALSE, 1);
233
234     /* subtitle */
235     w = gtk_label_new(subtitle);
236     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
237     formatted_text = g_strdup_printf("<span size=\"small\" foreground=\"black\">%s</span>", subtitle);
238     gtk_label_set_markup(GTK_LABEL(w), formatted_text);
239     g_free(formatted_text);
240     gtk_box_pack_start(GTK_BOX(text_vb), w, FALSE, FALSE, 1);
241
242     gtk_box_pack_start(GTK_BOX(item_hb), text_vb, TRUE, TRUE, 5);
243
244     return eb;
245 }
246
247
248 /* create the banner "above our heads" */
249 static GtkWidget *
250 welcome_header_new(void)
251 {
252     GtkWidget *item_vb;
253     GtkWidget *item_hb;
254     GtkWidget *eb;
255     GtkWidget *icon;
256     GString *message;
257     GtkWidget *w;
258     time_t secs = time(NULL);
259     struct tm *now = localtime(&secs);
260
261     item_vb = gtk_vbox_new(FALSE, 0);
262
263     /* colorize vbox */
264     eb = gtk_event_box_new();
265     gtk_container_add(GTK_CONTAINER(eb), item_vb);
266     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &header_bar_bg);
267
268     item_hb = gtk_hbox_new(FALSE, 0);
269     gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10);
270
271     icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);
272     gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10);
273
274     message = g_string_new("<span weight=\"bold\" size=\"x-large\" foreground=\"black\">");
275     if ((now->tm_mon == 3 && now->tm_mday == 1) || (now->tm_mon == 6 && now->tm_mday == 14)) {
276         g_string_append(message, "Sniffing the glue that holds the Internet together");
277     } else {
278         g_string_append(message, prefs.gui_start_title);
279     }
280     g_string_append(message, "</span>");
281
282     if (prefs.gui_version_in_start_page) {
283         g_string_append_printf(message, "\n<span size=\"large\" foreground=\"black\">Version " VERSION "%s</span>",
284                                wireshark_svnversion);
285     }
286
287     w = gtk_label_new(message->str);
288     gtk_label_set_markup(GTK_LABEL(w), message->str);
289     g_string_free(message, TRUE);
290     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
291     gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
292
293     gtk_widget_show_all(eb);
294
295     return eb;
296 }
297
298
299 /* create a "topic header widget" */
300 static GtkWidget *
301 welcome_topic_header_new(const char *header)
302 {
303     GtkWidget *w;
304     GtkWidget *eb;
305     gchar *formatted_message;
306
307
308     w = gtk_label_new(header);
309     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\" foreground=\"black\">%s</span>", header);
310     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
311     g_free(formatted_message);
312
313     /* colorize vbox */
314     eb = gtk_event_box_new();
315     gtk_container_add(GTK_CONTAINER(eb), w);
316     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_header_bg);
317
318     return eb;
319 }
320
321
322 /* create a "topic widget" */
323 static GtkWidget *
324 welcome_topic_new(const char *header, GtkWidget **to_fill)
325 {
326     GtkWidget *topic_vb;
327     GtkWidget *layout_vb;
328     GtkWidget *topic_eb;
329     GtkWidget *topic_header;
330
331
332     topic_vb = gtk_vbox_new(FALSE, 0);
333
334     topic_header = welcome_topic_header_new(header);
335     gtk_box_pack_start(GTK_BOX(topic_vb), topic_header, FALSE, FALSE, 0);
336
337     layout_vb = gtk_vbox_new(FALSE, 5);
338     gtk_container_set_border_width(GTK_CONTAINER(layout_vb), 10);
339     gtk_box_pack_start(GTK_BOX(topic_vb), layout_vb, FALSE, FALSE, 0);
340
341     /* colorize vbox (we need an event box for this!) */
342     topic_eb = gtk_event_box_new();
343     gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb);
344     gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &topic_content_bg);
345     *to_fill = layout_vb;
346
347     return topic_eb;
348 }
349
350
351 /* a file link was pressed */
352 static gboolean
353 welcome_filename_link_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data)
354 {
355     menu_open_filename(data);
356
357     return FALSE;
358 }
359
360
361 /* create a "file link widget" */
362 static GtkWidget *
363 welcome_filename_link_new(const gchar *filename, GtkWidget **label)
364 {
365     GtkWidget *w;
366     GtkWidget *eb;
367     GString             *str;
368     const unsigned int max = 60;
369     int err;
370     struct stat stat_buf;
371     GtkTooltips *tooltips;
372
373
374     tooltips = gtk_tooltips_new();
375
376     /* filename */
377     str = g_string_new(filename);
378
379     /* cut max filename length */
380     if( (str->len > max) && (str->len-(max) > 5) ) {
381         g_string_erase(str, 20, str->len-(max+5));
382         g_string_insert(str, 20, " ... ");
383     }
384
385     /* add file size */
386     err = ws_stat(filename, &stat_buf);
387     if(err == 0) {
388         if (stat_buf.st_size/1024/1024 > 10) {
389             g_string_append_printf(str, " %" G_GINT64_MODIFIER "dMB", (gint64) (stat_buf.st_size/1024/1024));
390         } else if (stat_buf.st_size/1024 > 10) {
391             g_string_append_printf(str, " %" G_GINT64_MODIFIER "dKB", (gint64) (stat_buf.st_size/1024));
392         } else {
393             g_string_append_printf(str, " %" G_GINT64_MODIFIER "d Bytes", (gint64) (stat_buf.st_size));
394         }
395     } else {
396         g_string_append(str, " [not found]");
397     }
398
399     /* pango format string */
400     if(err == 0) {
401         g_string_prepend(str, "<span foreground='blue'>");
402         g_string_append(str, "</span>");
403     }
404
405     /* label */
406     w = gtk_label_new(str->str);
407     *label = w;
408     gtk_label_set_markup(GTK_LABEL(w), str->str);
409     gtk_misc_set_padding(GTK_MISC(w), 5, 2);
410
411         /* event box */
412     eb = gtk_event_box_new();
413     gtk_container_add(GTK_CONTAINER(eb), w);
414     gtk_tooltips_set_tip(tooltips, eb, filename, "");
415     if(err != 0) {
416         gtk_widget_set_sensitive(w, FALSE);
417     }
418
419     g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), w);
420     g_signal_connect(eb, "leave-notify-event", G_CALLBACK(welcome_item_leave_cb), w);
421     g_signal_connect(eb, "button-press-event", G_CALLBACK(welcome_filename_link_press_cb), (gchar *) filename);
422
423     g_string_free(str, TRUE);
424
425     return eb;
426 }
427
428
429 /* reset the list of recent files */
430 void
431 main_welcome_reset_recent_capture_files(void)
432 {
433     GtkWidget *child_box;
434     GList* child_list;
435     GList* child_list_item;
436
437
438     if(welcome_file_panel_vb) {
439         child_box = scroll_box_dynamic_reset(welcome_file_panel_vb);
440         child_list = gtk_container_get_children(GTK_CONTAINER(child_box));
441         child_list_item = child_list;
442
443         while(child_list_item) {
444             gtk_container_remove(GTK_CONTAINER(child_box), child_list_item->data);
445             child_list_item = g_list_next(child_list_item);
446         }
447
448         g_list_free(child_list);
449     }
450 }
451
452
453 /* add a new file to the list of recent files */
454 void
455 main_welcome_add_recent_capture_files(const char *widget_cf_name)
456 {
457     GtkWidget *w;
458     GtkWidget *child_box;
459     GtkWidget *label;
460
461
462     w = welcome_filename_link_new(widget_cf_name, &label);
463     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_item_idle_bg);
464     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
465     child_box = scroll_box_dynamic_add(welcome_file_panel_vb);
466     gtk_box_pack_start(GTK_BOX(child_box), w, FALSE, FALSE, 0);
467     gtk_widget_show_all(w);
468     gtk_widget_show_all(child_box);
469 }
470
471
472 #ifdef HAVE_LIBPCAP
473 /* user clicked on an interface button */
474 static gboolean
475 welcome_if_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data)
476 {
477     if (global_capture_opts.iface)
478         g_free(global_capture_opts.iface);
479     if (global_capture_opts.iface_descr)
480         g_free(global_capture_opts.iface_descr);
481
482     global_capture_opts.iface = g_strdup(data);
483     global_capture_opts.iface_descr = NULL;
484     /* XXX - fix this */
485     /*global_capture_opts.iface_descr = get_interface_descriptive_name(global_capture_opts.iface);*/
486
487     /* XXX - remove this? */
488     if (global_capture_opts.save_file) {
489         g_free(global_capture_opts.save_file);
490         global_capture_opts.save_file = NULL;
491     }
492
493 #ifdef HAVE_AIRPCAP
494     airpcap_if_active = get_airpcap_if_from_name(airpcap_if_list, global_capture_opts.iface);
495     airpcap_if_selected = airpcap_if_active;
496     airpcap_set_toolbar_start_capture(airpcap_if_active);
497 #endif
498
499     capture_start_cb(NULL, NULL);
500
501     return FALSE;
502 }
503
504
505 /* create a single interface entry */
506 static GtkWidget *
507 welcome_if_new(const char *if_name, GdkColor *topic_bg _U_, gpointer interf)
508 {
509     GtkWidget *interface_hb;
510     GtkWidget *w;
511     GString   *message;
512     GtkWidget *eb;
513
514
515     /* event box */
516     eb = gtk_event_box_new();
517     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &topic_item_idle_bg);
518
519     g_signal_connect(eb, "enter-notify-event", G_CALLBACK(welcome_item_enter_cb), NULL);
520     g_signal_connect(eb, "leave-notify-event", G_CALLBACK(welcome_item_leave_cb), NULL);
521     g_signal_connect(eb, "button-press-event", G_CALLBACK(welcome_if_press_cb), interf);
522
523     interface_hb = gtk_hbox_new(FALSE, 5);
524     gtk_container_add(GTK_CONTAINER(eb), interface_hb);
525
526     /* icon */
527     w = gtk_image_new_from_stock(WIRESHARK_STOCK_CAPTURE_START, GTK_ICON_SIZE_SMALL_TOOLBAR);
528     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 5);
529
530     message = g_string_new(if_name);
531
532     /* truncate string if it's too long */
533     /* (the number of chars is a bit arbitrary, though) */
534     if(message->len > 48) {
535         g_string_truncate(message, 45);
536         g_string_append  (message, " ...");
537     }
538     g_string_prepend(message, "<span foreground='blue'>");
539     g_string_append (message, "</span>");
540     w = gtk_label_new(message->str);
541     gtk_label_set_markup(GTK_LABEL(w), message->str);
542     g_string_free(message, TRUE);
543
544     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
545     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
546
547     return eb;
548 }
549
550
551 /* load the list of interfaces */
552 static void
553 welcome_if_panel_load(void)
554 {
555   GtkWidget *child_box;
556   GtkWidget *interface_hb;
557
558   if_info_t     *if_info;
559   GList         *if_list;
560   int err;
561   gchar         *err_str;
562   int           ifs;
563   GList         *curr;
564   gchar         *descr;
565
566
567   /* LOAD THE INTERFACES */
568   if_list = capture_interface_list(&err, &err_str);
569   if_list = g_list_sort (if_list, if_list_comparator_alph);
570   if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
571     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", err_str);
572     g_free(err_str);
573     return;
574   }
575
576   /* List the interfaces */
577   for(ifs = 0; (curr = g_list_nth(if_list, ifs)); ifs++) {
578       /*g_string_assign(if_tool_str, "");*/
579       if_info = curr->data;
580
581       /* Continue if capture device is hidden */
582       if (prefs_is_capture_device_hidden(if_info->name)) {
583           continue;
584       }
585
586       descr = capture_dev_user_descr_find(if_info->name);
587       if (descr) {
588 #ifndef _WIN32
589         gchar *comment = descr;
590         descr = g_strdup_printf("%s (%s)", comment, if_info->name);
591         g_free (comment);
592 #endif
593         interface_hb = welcome_if_new(descr, &topic_content_bg, g_strdup(if_info->name));
594         g_free (descr);
595       } else if (if_info->description != NULL) {
596         interface_hb = welcome_if_new(if_info->description, &topic_content_bg, g_strdup(if_info->name));
597       } else {
598         interface_hb = welcome_if_new(if_info->name, &topic_content_bg, g_strdup(if_info->name));
599       }
600
601       child_box = scroll_box_dynamic_add(welcome_if_panel_vb);
602       gtk_box_pack_start(GTK_BOX(child_box), interface_hb, FALSE, FALSE, 1);
603   }
604
605   free_interface_list(if_list);
606 }
607 #endif  /* HAVE_LIBPCAP */
608
609 /* reload the list of interfaces */
610 void
611 welcome_if_panel_reload(void)
612 {
613 #ifdef HAVE_LIBPCAP
614     GtkWidget *child_box;
615     GList* child_list;
616     GList* child_list_item;
617
618
619     if(welcome_if_panel_vb) {
620         child_box = scroll_box_dynamic_reset(welcome_if_panel_vb);
621         child_list = gtk_container_get_children(GTK_CONTAINER(child_box));
622         child_list_item = child_list;
623
624         while(child_list_item) {
625             gtk_container_remove(GTK_CONTAINER(child_box), child_list_item->data);
626             child_list_item = g_list_next(child_list_item);
627         }
628
629         g_list_free(child_list);
630
631         welcome_if_panel_load();
632         gtk_widget_show_all(welcome_if_panel_vb);
633     }
634 #endif  /* HAVE_LIBPCAP */
635 }
636
637
638 /* create the welcome page */
639 GtkWidget *
640 welcome_new(void)
641 {
642     GtkWidget *welcome_scrollw;
643     GtkWidget *welcome_vb;
644     GtkWidget *welcome_hb;
645     GtkWidget *column_vb;
646     GtkWidget *item_hb;
647     GtkWidget *w;
648     GtkWidget *header;
649     GtkWidget *topic_vb;
650     GtkWidget *topic_to_fill;
651 #ifdef HAVE_LIBPCAP
652     GtkWidget *if_child_box;
653 #endif  /* HAVE_LIBPCAP */
654     GtkWidget *file_child_box;
655     gchar *label_text;
656
657
658     /* prepare colors */
659     /* header bar background color */
660     header_bar_bg.pixel = 0;
661     header_bar_bg.red = 154 * 255;
662     header_bar_bg.green = 210 * 255;
663     header_bar_bg.blue = 229 * 255;
664     get_color(&header_bar_bg);
665
666     /* topic header background color */
667     topic_header_bg.pixel = 0;
668     topic_header_bg.red = 24 * 255;
669     topic_header_bg.green = 151 * 255;
670     topic_header_bg.blue = 192 * 255;
671     get_color(&topic_header_bg);
672
673     /* topic content background color */
674     topic_content_bg.pixel = 0;
675     topic_content_bg.red = 221 * 255;
676     topic_content_bg.green = 226 * 255;
677     topic_content_bg.blue = 228 * 255;
678     get_color(&topic_content_bg);
679
680     /* topic item idle background color */
681     /*topic_item_idle_bg.pixel = 0;
682     topic_item_idle_bg.red = 216 * 255;
683     topic_item_idle_bg.green = 221 * 255;
684     topic_item_idle_bg.blue = 223 * 255;
685     get_color(&topic_item_idle_bg);*/
686
687     topic_item_idle_bg = topic_content_bg;
688
689     /* topic item entered color */
690     topic_item_entered_bg.pixel = 0;
691     topic_item_entered_bg.red = 211 * 255;
692     topic_item_entered_bg.green = 216 * 255;
693     topic_item_entered_bg.blue = 218 * 255;
694     get_color(&topic_item_entered_bg);
695
696     /*topic_item_entered_bg.pixel = 0;
697     topic_item_entered_bg.red = 216 * 255;
698     topic_item_entered_bg.green = 221 * 255;
699     topic_item_entered_bg.blue = 223 * 255;
700     get_color(&topic_item_entered_bg);*/
701
702     /*topic_item_entered_bg.pixel = 0;
703     topic_item_entered_bg.red = 154 * 255;
704     topic_item_entered_bg.green = 210 * 255;
705     topic_item_entered_bg.blue = 229 * 255;
706     get_color(&topic_item_entered_bg);*/
707
708
709     welcome_scrollw = scrolled_window_new(NULL, NULL);
710
711     welcome_vb = gtk_vbox_new(FALSE, 0);
712
713     /* header */
714     header = welcome_header_new();
715     gtk_box_pack_start(GTK_BOX(welcome_vb), header, FALSE, FALSE, 0);
716
717     /* content */
718     welcome_hb = gtk_hbox_new(FALSE, 10);
719     gtk_container_set_border_width(GTK_CONTAINER(welcome_hb), 10);
720     gtk_box_pack_start(GTK_BOX(welcome_vb), welcome_hb, TRUE, TRUE, 0);
721
722
723     /* column capture */
724     column_vb = gtk_vbox_new(FALSE, 10);
725     gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
726
727     /* capture topic */
728     topic_vb = welcome_topic_new("Capture", &topic_to_fill);
729     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
730
731 #ifdef HAVE_LIBPCAP
732     item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_INTERFACES,
733         "Interface List",
734                 "Live list of the capture interfaces (counts incoming packets)",
735         "Same as Capture/Interfaces menu or toolbar item",
736         GTK_SIGNAL_FUNC(capture_if_cb), NULL);
737     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
738
739     label_text =  g_strdup_printf("<span foreground=\"black\">Start capture on interface:</span>");
740     w = gtk_label_new(label_text);
741     gtk_label_set_markup(GTK_LABEL(w), label_text);
742     g_free (label_text);
743     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
744     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
745
746     if_child_box = gtk_vbox_new(FALSE, 0);
747     /* 8 capture interfaces or 150 pixels height is about the size */
748     /* that still fits on a screen of about 1000*700 */
749     welcome_if_panel_vb = scroll_box_dynamic_new(GTK_BOX(if_child_box), 8, 150);
750     gtk_box_pack_start(GTK_BOX(topic_to_fill), welcome_if_panel_vb, FALSE, FALSE, 0);
751     welcome_if_panel_load();
752
753     item_hb = welcome_button(WIRESHARK_STOCK_CAPTURE_OPTIONS,
754         "Capture Options",
755                 "Start a capture with detailed options",
756         "Same as Capture/Options menu or toolbar item",
757         GTK_SIGNAL_FUNC(capture_prep_cb), NULL);
758     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
759
760     /* capture help topic */
761     topic_vb = welcome_topic_new("Capture Help", &topic_to_fill);
762     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
763
764     item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
765                 "How to Capture",
766                 "Step by step to a successful capture setup",
767         topic_online_url(ONLINEPAGE_CAPTURE_SETUP),
768         GTK_SIGNAL_FUNC(topic_menu_cb), GINT_TO_POINTER(ONLINEPAGE_CAPTURE_SETUP));
769     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
770
771     item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
772                 "Network Media",
773         "Specific information for capturing on: Ethernet, WLAN, ...",
774         topic_online_url(ONLINEPAGE_NETWORK_MEDIA),
775         GTK_SIGNAL_FUNC(topic_menu_cb), GINT_TO_POINTER(ONLINEPAGE_NETWORK_MEDIA));
776     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
777 #else
778     label_text =  g_strdup_printf("<span foreground=\"black\">Capturing is not compiled into this version of Wireshark!</span>");
779     w = gtk_label_new(label_text);
780     gtk_label_set_markup(GTK_LABEL(w), label_text);
781     g_free (label_text);
782     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
783     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
784 #endif  /* HAVE_LIBPCAP */
785
786     /* fill bottom space */
787     w = gtk_label_new("");
788     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
789
790
791     /* column files */
792     topic_vb = welcome_topic_new("Files", &topic_to_fill);
793     gtk_box_pack_start(GTK_BOX(welcome_hb), topic_vb, TRUE, TRUE, 0);
794
795     item_hb = welcome_button(GTK_STOCK_OPEN,
796         "Open",
797                 "Open a previously captured file",
798         "Same as File/Open menu or toolbar item",
799         GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
800     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
801
802     /* prepare list of recent files (will be filled in later) */
803     label_text =  g_strdup_printf("<span foreground=\"black\">Open Recent:</span>");
804     w = gtk_label_new(label_text);
805     gtk_label_set_markup(GTK_LABEL(w), label_text);
806     g_free (label_text);
807     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
808     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
809
810     file_child_box = gtk_vbox_new(FALSE, 1);
811     /* 17 file items or 300 pixels height is about the size */
812     /* that still fits on a screen of about 1000*700 */
813     welcome_file_panel_vb = scroll_box_dynamic_new(GTK_BOX(file_child_box), 17, 300);
814     gtk_box_pack_start(GTK_BOX(topic_to_fill), welcome_file_panel_vb, FALSE, FALSE, 0);
815
816     item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
817         "Sample Captures",
818                 "A rich assortment of example capture files on the wiki",
819         topic_online_url(ONLINEPAGE_SAMPLE_CAPTURES),
820         GTK_SIGNAL_FUNC(topic_menu_cb), GINT_TO_POINTER(ONLINEPAGE_SAMPLE_CAPTURES));
821     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
822
823     /* fill bottom space */
824     w = gtk_label_new("");
825     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
826
827
828     /* column online */
829     column_vb = gtk_vbox_new(FALSE, 10);
830     gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
831
832     /* topic online */
833     topic_vb = welcome_topic_new("Online", &topic_to_fill);
834     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
835
836     item_hb = welcome_button(GTK_STOCK_HOME,
837         "Website",
838                 "Visit the project's website",
839         topic_online_url(ONLINEPAGE_HOME),
840         GTK_SIGNAL_FUNC(topic_menu_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
841     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
842
843     item_hb = welcome_button(GTK_STOCK_HELP,
844         "User's Guide",
845                 "The User's Guide (local version, if installed)",
846         "Locally installed (if installed) otherwise online version",
847         GTK_SIGNAL_FUNC(topic_menu_cb), GINT_TO_POINTER(HELP_CONTENT));
848     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
849
850     item_hb = welcome_button(WIRESHARK_STOCK_WIKI,
851         "Security",
852                 "Work with Wireshark as securely as possible",
853         topic_online_url(ONLINEPAGE_SECURITY),
854         GTK_SIGNAL_FUNC(topic_menu_cb), GINT_TO_POINTER(ONLINEPAGE_SECURITY));
855     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
856
857 #if 0
858     /* XXX - add this, once the Windows update functionality is implemented */
859     /* topic updates */
860     topic_vb = welcome_topic_new("Updates", &topic_to_fill);
861     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
862
863     label_text =  g_strdup_printf("<span foreground=\"black\">No updates available!</span>");
864     w = gtk_label_new(label_text);
865     gtk_label_set_markup(GTK_LABEL(w), label_text);
866     g_free (label_text);
867     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
868 #endif
869
870
871     /* the end */
872     gtk_widget_show_all(welcome_vb);
873
874     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
875                                           welcome_vb);
876     gtk_widget_show_all(welcome_scrollw);
877
878     return welcome_scrollw;
879 }
880