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