Remove redundant (repeated) "PortAudio" from "About Wireshark" screen.
[obnox/wireshark/wip.git] / gtk / main.c
1 /* main.c
2  *
3  * $Id$
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10  *                              needed by dissect routines
11  * Jeff Foster,    2001/03/12,  added support tabbed hex display windowss
12  *
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
27  */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include <gtk/gtk.h>
34 #include <gdk/gdkkeysyms.h>
35
36 #include <string.h>
37 #include <ctype.h>
38
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #ifdef NEED_STRERROR_H
44 #include "strerror.h"
45 #endif
46
47 #ifdef NEED_GETOPT_H
48 #include "getopt.h"
49 #endif
50
51 #ifdef _WIN32 /* Needed for console I/O */
52 #include <fcntl.h>
53 #include <conio.h>
54 #endif
55
56 #ifdef HAVE_LIBPORTAUDIO
57 #include <portaudio.h>
58 #endif /* HAVE_LIBPORTAUDIO */
59
60 #include <epan/epan.h>
61 #include <epan/filesystem.h>
62 #include <epan/privileges.h>
63 #include <epan/epan_dissect.h>
64 #include <epan/timestamp.h>
65 #include <epan/packet.h>
66 #include <epan/plugins.h>
67 #include <epan/dfilter/dfilter.h>
68 #include <epan/strutil.h>
69 #include <epan/addr_resolv.h>
70 #include <epan/emem.h>
71 #include <epan/ex-opt.h>
72 #include <epan/funnel.h>
73 #include <epan/expert.h>
74 #include <epan/frequency-utils.h>
75
76 /* general (not GTK specific) */
77 #include "file.h"
78 #include "summary.h"
79 #include "filters.h"
80 #include "disabled_protos.h"
81 #include <epan/prefs.h>
82 #include "filter_dlg.h"
83 #include "layout_prefs.h"
84 #include "color.h"
85 #include "color_filters.h"
86 #include "print.h"
87 #include "simple_dialog.h"
88 #include "register.h"
89 #include <epan/prefs-int.h>
90 #include "ringbuffer.h"
91 #include "../ui_util.h"
92 #include <epan/tap.h>
93 #include <epan/stat_cmd_args.h>
94 #include "util.h"
95 #include "clopts_common.h"
96 #include "cmdarg_err.h"
97 #include "version_info.h"
98 #include "merge.h"
99 #include "u3.h"
100 #include "uat_gui.h"
101 #include "epan/uat.h"
102
103
104 #ifdef HAVE_LIBPCAP
105 #include "capture-pcap-util.h"
106 #include "capture.h"
107 #include "capture_sync.h"
108 #endif
109
110 #ifdef _WIN32
111 #include "capture-wpcap.h"
112 #include "capture_wpcap_packet.h"
113 #include <tchar.h> /* Needed for Unicode */
114 #if GTK_MAJOR_VERSION >= 2
115 #include <commctrl.h>
116 #endif /* GTK_MAJOR_VERSION >= 2 */
117 #endif /* _WIN32 */
118
119 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
120 #include "ethclist.h"
121 #endif
122
123 /* GTK related */
124 #include "statusbar.h"
125 #include "alert_box.h"
126 #if 0
127 #include "dlg_utils.h"
128 #endif
129 #include "file_dlg.h"
130 #include "gtkglobals.h"
131 #include "colors.h"
132 #include "gui_utils.h"
133 #include "compat_macros.h"
134 #include "color_dlg.h"
135
136 #include "main.h"
137 #include "menu.h"
138 #include "../main_window.h"
139 #include "../menu.h"
140 #include "capture_file_dlg.h"
141 #include <epan/column.h>
142 #include "proto_draw.h"
143 #include "keys.h"
144 #include "packet_win.h"
145 #include "toolbar.h"
146 #include "find_dlg.h"
147 #include "packet_list.h"
148 #include "recent.h"
149 #include "follow_tcp.h"
150 #include "font_utils.h"
151 #include "about_dlg.h"
152 #include "help_dlg.h"
153 #include "decode_as_dlg.h"
154 #include "webbrowser.h"
155 #include "capture_dlg.h"
156 #include "capture_ui_utils.h"
157 #include "log.h"
158 #include "../epan/emem.h"
159 #include "file_util.h"
160 #if GTK_MAJOR_VERSION >= 2
161 #ifdef HAVE_LIBPCAP
162 #include "../image/wsicon16.xpm"
163 #include "../image/wsicon32.xpm"
164 #include "../image/wsicon48.xpm"
165 #include "../image/wsicon64.xpm"
166 #include "../image/wsiconcap16.xpm"
167 #include "../image/wsiconcap32.xpm"
168 #include "../image/wsiconcap48.xpm"
169 #endif
170 #endif
171 #ifdef SHOW_WELCOME_PAGE
172 #include "../image/wssplash.xpm"
173 #endif
174
175 #ifdef HAVE_AIRPCAP
176 #include <airpcap.h>
177 #include "airpcap_loader.h"
178 #include "airpcap_dlg.h"
179 #include "airpcap_gui_utils.h"
180
181 #include "./gtk/toolbar.h"
182
183 #include "./image/toolbar/wep_closed_24.xpm"
184 #endif
185
186 #ifdef  HAVE_AIRPDCAP
187 /*      Davide Schiera (2006-11-22): including AirPDcap project                                                 */
188 #include <epan/crypt/airpdcap_ws.h>
189 /* Davide Schiera (2006-11-22) ----------------------------------------------   */
190 #endif
191
192 #ifdef NEED_G_ASCII_STRCASECMP_H
193 #include "../epan/g_ascii_strcasecmp.h"
194 #endif
195
196 /*
197  * Files under personal and global preferences directories in which
198  * GTK settings for Wireshark are stored.
199  */
200 #define RC_FILE "gtkrc"
201
202 #ifdef HAVE_LIBPCAP
203 #define DEF_READY_MESSAGE " Ready to load or capture"
204 #else
205 #define DEF_READY_MESSAGE " Ready to load file"
206 #endif
207
208 capture_file cfile;
209 GtkWidget   *main_display_filter_widget=NULL;
210 GtkWidget   *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
211 GtkWidget   *pkt_scrollw;
212 static GtkWidget   *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
213 static GtkWidget   *main_first_pane, *main_second_pane;
214 static GtkWidget   *status_pane_left, *status_pane_right;
215 static GtkWidget   *menubar, *main_vbox, *main_tb, *stat_hbox, *filter_tb;
216 static GtkWidget   *priv_warning_dialog;
217
218 #ifdef HAVE_AIRPCAP
219 GtkWidget *airpcap_tb;
220 static GtkWidget *driver_warning_dialog;
221 static int    airpcap_dll_ret_val = -1;
222 #endif
223
224 /*
225  * The order below defines the priority of info bar contexts.
226  */
227 typedef enum {
228     STATUS_LEVEL_MAIN,
229     STATUS_LEVEL_FILE,
230     STATUS_LEVEL_FILTER,
231     STATUS_LEVEL_HELP,
232     NUM_STATUS_LEVELS
233 } status_level_e;
234
235 static GtkWidget    *info_bar;
236 static GtkWidget    *packets_bar = NULL;
237 static GtkWidget    *profile_bar = NULL;
238 static GtkWidget    *welcome_pane;
239 static guint        main_ctx, file_ctx, help_ctx, filter_ctx;
240 static guint        status_levels[NUM_STATUS_LEVELS];
241 static guint        packets_ctx;
242 static guint        profile_ctx;
243 static gchar        *packets_str = NULL;
244 static gchar        *profile_str = NULL;
245 GString *comp_info_str, *runtime_info_str;
246 gboolean have_capture_file = FALSE; /* XXX - is there an equivalent in cfile? */
247
248 #ifdef _WIN32
249 static gboolean has_console;    /* TRUE if app has console */
250 static void destroy_console(void);
251 #endif
252 static void console_log_handler(const char *log_domain,
253     GLogLevelFlags log_level, const char *message, gpointer user_data);
254
255 #ifdef HAVE_LIBPCAP
256 static gboolean list_link_layer_types;
257 capture_options global_capture_opts;
258 capture_options *capture_opts = &global_capture_opts;
259 #endif
260
261 gboolean block_toolbar_signals = FALSE;
262
263 static void create_main_window(gint, gint, gint, e_prefs*);
264 static void show_main_window(gboolean);
265 static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
266 static void main_save_window_geometry(GtkWidget *widget);
267
268 #define E_DFILTER_CM_KEY          "display_filter_combo"
269 #define E_DFILTER_FL_KEY          "display_filter_list"
270
271 /* Match selected byte pattern */
272 static void
273 match_selected_cb_do(gpointer data, int action, gchar *text)
274 {
275     GtkWidget  *filter_te;
276     char       *cur_filter, *new_filter;
277
278     if ((!text) || (0 == strlen(text))) {
279         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to build a filter!\nTry expanding or choosing another item.");
280         return;
281     }
282
283     g_assert(data);
284     filter_te = OBJECT_GET_DATA(data, E_DFILTER_TE_KEY);
285     g_assert(filter_te);
286
287     cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
288
289     switch (action&MATCH_SELECTED_MASK) {
290
291     case MATCH_SELECTED_REPLACE:
292         new_filter = g_strdup(text);
293         break;
294
295     case MATCH_SELECTED_AND:
296         if ((!cur_filter) || (0 == strlen(cur_filter)))
297             new_filter = g_strdup(text);
298         else
299             new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
300         break;
301
302     case MATCH_SELECTED_OR:
303         if ((!cur_filter) || (0 == strlen(cur_filter)))
304             new_filter = g_strdup(text);
305         else
306             new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
307         break;
308
309     case MATCH_SELECTED_NOT:
310         new_filter = g_strconcat("!(", text, ")", NULL);
311         break;
312
313     case MATCH_SELECTED_AND_NOT:
314         if ((!cur_filter) || (0 == strlen(cur_filter)))
315             new_filter = g_strconcat("!(", text, ")", NULL);
316         else
317             new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
318         break;
319
320     case MATCH_SELECTED_OR_NOT:
321         if ((!cur_filter) || (0 == strlen(cur_filter)))
322             new_filter = g_strconcat("!(", text, ")", NULL);
323         else
324             new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
325         break;
326
327     default:
328         g_assert_not_reached();
329         new_filter = NULL;
330         break;
331     }
332
333     /* Free up the copy we got of the old filter text. */
334     g_free(cur_filter);
335
336     /* Don't change the current display filter if we only want to copy the filter */
337     if (action&MATCH_SELECTED_COPY_ONLY) {
338         GString *gtk_text_str = g_string_new("");
339         g_string_sprintfa(gtk_text_str, "%s", new_filter);
340         copy_to_clipboard(gtk_text_str);
341         g_string_free(gtk_text_str, TRUE);
342     } else {
343         /* create a new one and set the display filter entry accordingly */
344         gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
345
346         /* Run the display filter so it goes in effect. */
347         if (action&MATCH_SELECTED_APPLY_NOW)
348             main_filter_packets(&cfile, new_filter, FALSE);
349     }
350
351     /* Free up the new filter text. */
352     g_free(new_filter);
353 }
354
355 void
356 match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
357 {
358     char *filter = NULL;
359
360     if (cfile.finfo_selected) {
361         filter = proto_construct_match_selected_string(cfile.finfo_selected,
362                                                        cfile.edt);
363         match_selected_cb_do((data ? data : w), action, filter);
364     }
365 }
366
367 void
368 colorize_selected_ptree_cb(GtkWidget *w _U_, gpointer data _U_, guint8 filt_nr)
369 {
370     char *filter = NULL;
371
372     if (cfile.finfo_selected) {
373         filter = proto_construct_match_selected_string(cfile.finfo_selected,
374                                                        cfile.edt);
375         if ((!filter) || (0 == strlen(filter))) {
376             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
377                 "Could not acquire information to build a filter!\n"
378                 "Try expanding or choosing another item.");
379             return;
380         }
381
382         if (filt_nr==0) {
383             color_display_with_filter(filter);
384         } else {
385             if (filt_nr==255) {
386                 color_filters_reset_tmp();
387             } else {
388                 color_filters_set_tmp(filt_nr,filter, FALSE);
389             }
390             cf_colorize_packets(&cfile);
391         }
392     }
393 }
394
395
396 static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
397 {
398     gchar *selected_proto_url;
399     gchar *proto_abbrev = data;
400
401
402     switch(btn) {
403     case(ESD_BTN_OK):
404         if (cfile.finfo_selected) {
405             /* open wiki page using the protocol abbreviation */
406             selected_proto_url = g_strdup_printf("http://wiki.wireshark.org/Protocols/%s", proto_abbrev);
407             browser_open_url(selected_proto_url);
408             g_free(selected_proto_url);
409         }
410         break;
411     case(ESD_BTN_CANCEL):
412         break;
413     default:
414         g_assert_not_reached();
415     }
416 }
417
418
419 void
420 selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
421 {
422     int field_id;
423     const gchar *proto_abbrev;
424     gpointer  dialog;
425
426
427     if (cfile.finfo_selected) {
428         /* convert selected field to protocol abbreviation */
429         /* XXX - could this conversion be simplified? */
430         field_id = cfile.finfo_selected->hfinfo->id;
431         /* if the selected field isn't a protocol, get it's parent */
432         if(!proto_registrar_is_protocol(field_id)) {
433             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
434         }
435
436         proto_abbrev = proto_registrar_get_abbrev(field_id);
437
438         /* ask the user if the wiki page really should be opened */
439         dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
440                     PRIMARY_TEXT_START "Open Wireshark Wiki page of protocol \"%s\"?" PRIMARY_TEXT_END "\n"
441                     "\n"
442                     "This will open the \"%s\" related Wireshark Wiki page in your Web browser.\n"
443                     "\n"
444                     "The Wireshark Wiki is a collaborative approach to provide information\n"
445                     "about Wireshark in several ways (not limited to protocol specifics).\n"
446                     "\n"
447                     "This Wiki is new, so the page of the selected protocol\n"
448                     "may not exist and/or may not contain valuable information.\n"
449                     "\n"
450                     "As everyone can edit the Wiki and add new content (or extend existing),\n"
451                     "you are encouraged to add information if you can.\n"
452                     "\n"
453                     "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
454                     "\n"
455                     "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
456                     "which will save you a lot of editing and will give a consistent look over the pages.",
457                     proto_abbrev, proto_abbrev);
458         simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, (gpointer) proto_abbrev);
459     }
460 }
461
462
463 void
464 selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
465 {
466     int field_id;
467     const gchar *proto_abbrev;
468     gchar *selected_proto_url;
469
470
471     if (cfile.finfo_selected) {
472         /* convert selected field to protocol abbreviation */
473         /* XXX - could this conversion be simplified? */
474         field_id = cfile.finfo_selected->hfinfo->id;
475         /* if the selected field isn't a protocol, get it's parent */
476         if(!proto_registrar_is_protocol(field_id)) {
477             field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
478         }
479
480         proto_abbrev = proto_registrar_get_abbrev(field_id);
481
482         /* open reference page using the protocol abbreviation */
483         selected_proto_url = g_strdup_printf("http://www.wireshark.org/docs/dfref/%c/%s.html", proto_abbrev[0], proto_abbrev);
484         browser_open_url(selected_proto_url);
485         g_free(selected_proto_url);
486     }
487 }
488
489 static gchar *
490 get_text_from_packet_list(gpointer data)
491 {
492     gint        row = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_ROW_KEY));
493     gint        column = GPOINTER_TO_INT(OBJECT_GET_DATA(data, E_MPACKET_LIST_COL_KEY));
494     frame_data *fdata = (frame_data *)packet_list_get_row_data(row);
495     epan_dissect_t *edt;
496     gchar      *buf=NULL;
497     int         len;
498     int         err;
499     gchar       *err_info;
500
501     if (fdata != NULL) {
502         if (!wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
503                        cfile.pd, fdata->cap_len, &err, &err_info)) {
504             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
505                           cf_read_error_message(err, err_info), cfile.filename);
506             return NULL;
507         }
508
509         edt = epan_dissect_new(FALSE, FALSE);
510         epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
511                          &cfile.cinfo);
512         epan_dissect_fill_in_columns(edt);
513
514         if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
515             strlen(cfile.cinfo.col_expr_val[column]) != 0) {
516             len = strlen(cfile.cinfo.col_expr[column]) +
517                   strlen(cfile.cinfo.col_expr_val[column]) + 5;
518             buf = ep_alloc0(len);
519             g_snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
520                      cfile.cinfo.col_expr_val[column]);
521         }
522
523         epan_dissect_free(edt);
524     }
525
526     return buf;
527 }
528
529 void
530 match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
531 {
532     match_selected_cb_do(data,
533         action,
534         get_text_from_packet_list(data));
535 }
536
537 /* This function allows users to right click in the details window and copy the text
538  * information to the operating systems clipboard.
539  *
540  * We first check to see if a string representation is setup in the tree and then
541  * read the string. If not available then we try to grab the value. If all else
542  * fails we display a message to the user to indicate the copy could not be completed.
543  */
544 void
545 copy_selected_plist_cb(GtkWidget *w _U_, gpointer data _U_)
546 {
547     GString *gtk_text_str = g_string_new("");
548     char labelstring[256];
549     char *stringpointer = labelstring;
550
551     if (cfile.finfo_selected->rep->representation != 0) {
552         g_string_sprintfa(gtk_text_str, "%s", cfile.finfo_selected->rep->representation);   /* Get the represented data */
553     }
554     if (gtk_text_str->len == 0) {                                                           /* If no representation then... */
555         proto_item_fill_label(cfile.finfo_selected, stringpointer);                         /* Try to read the value */
556         g_string_sprintfa(gtk_text_str, "%s", stringpointer);
557     }
558     if (gtk_text_str->len == 0) {                                                           /* Could not get item so display error msg */
559         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Could not acquire information to copy, try expanding or choosing another item");
560     }
561     else
562     {
563         copy_to_clipboard(gtk_text_str);                     /* Copy string to clipboard */
564     }
565     g_string_free(gtk_text_str, TRUE);                       /* Free the memory */
566 }
567
568
569 /* XXX: use a preference for this setting! */
570 static guint dfilter_combo_max_recent = 10;
571
572 /* add a display filter to the combo box */
573 /* Note: a new filter string will replace an old identical one */
574 static gboolean
575 dfilter_combo_add(GtkWidget *filter_cm, char *s) {
576     GList     *li;
577     GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
578
579
580     /* GtkCombos don't let us get at their list contents easily, so we maintain
581        our own filter list, and feed it to gtk_combo_set_popdown_strings when
582        a new filter is added. */
583     li = g_list_first(dfilter_list);
584     while (li) {
585         /* If the filter is already in the list, remove the old one and
586          * append the new one at the latest position (at g_list_append() below) */
587         if (li->data && strcmp(s, li->data) == 0) {
588             dfilter_list = g_list_remove(dfilter_list, li->data);
589             break;
590         }
591         li = li->next;
592     }
593
594     dfilter_list = g_list_append(dfilter_list, s);
595     OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
596     gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), dfilter_list);
597     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), g_list_last(dfilter_list)->data);
598
599     return TRUE;
600 }
601
602
603 /* write all non empty display filters (until maximum count)
604  * of the combo box GList to the user's recent file */
605 void
606 dfilter_recent_combo_write_all(FILE *rf) {
607   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
608   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
609   GList     *li;
610   guint      max_count = 0;
611
612
613   /* write all non empty display filter strings to the recent file (until max count) */
614   li = g_list_first(dfilter_list);
615   while ( li && (max_count++ <= dfilter_combo_max_recent) ) {
616     if (strlen(li->data)) {
617       fprintf (rf, RECENT_KEY_DISPLAY_FILTER ": %s\n", (char *)li->data);
618     }
619     li = li->next;
620   }
621 }
622
623 /* empty the combobox entry field */
624 void
625 dfilter_combo_add_empty(void) {
626   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
627
628   gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(filter_cm)->entry), "");
629 }
630
631
632 /* add a display filter coming from the user's recent file to the dfilter combo box */
633 gboolean
634 dfilter_combo_add_recent(gchar *s) {
635   GtkWidget *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
636   char      *dup;
637
638   dup = g_strdup(s);
639   if (!dfilter_combo_add(filter_cm, dup)) {
640     g_free(dup);
641     return FALSE;
642   }
643
644   return TRUE;
645 }
646
647
648 /* call cf_filter_packets() and add this filter string to the recent filter list */
649 gboolean
650 main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
651 {
652   GtkCombo  *filter_cm = OBJECT_GET_DATA(top_level, E_DFILTER_CM_KEY);
653   GList     *dfilter_list = OBJECT_GET_DATA(filter_cm, E_DFILTER_FL_KEY);
654   GList     *li;
655   gboolean   add_filter = TRUE;
656   gboolean   free_filter = TRUE;
657   char      *s;
658   cf_status_t cf_status;
659
660   s = g_strdup(dftext);
661
662   cf_status = cf_filter_packets(cf, s, force);
663   if (!s)
664     return (cf_status == CF_OK);
665
666   /* GtkCombos don't let us get at their list contents easily, so we maintain
667      our own filter list, and feed it to gtk_combo_set_popdown_strings when
668      a new filter is added. */
669   if (cf_status == CF_OK) {
670     li = g_list_first(dfilter_list);
671     while (li) {
672       if (li->data && strcmp(s, li->data) == 0)
673         add_filter = FALSE;
674       li = li->next;
675     }
676
677     if (add_filter) {
678       /* trim list size first */
679       while (g_list_length(dfilter_list) >= dfilter_combo_max_recent) {
680         dfilter_list = g_list_remove(dfilter_list, g_list_first(dfilter_list)->data);
681       }
682
683       free_filter = FALSE;
684       dfilter_list = g_list_append(dfilter_list, s);
685       OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
686       gtk_combo_set_popdown_strings(filter_cm, dfilter_list);
687       gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(dfilter_list)->data);
688     }
689   }
690   if (free_filter)
691     g_free(s);
692
693   return (cf_status == CF_OK);
694 }
695
696
697 /* Run the current display filter on the current packet set, and
698    redisplay. */
699 static void
700 filter_activate_cb(GtkWidget *w _U_, gpointer data)
701 {
702   const char *s;
703
704   s = gtk_entry_get_text(GTK_ENTRY(data));
705
706   main_filter_packets(&cfile, s, FALSE);
707 }
708
709 /* redisplay with no display filter */
710 static void
711 filter_reset_cb(GtkWidget *w, gpointer data _U_)
712 {
713   GtkWidget *filter_te = NULL;
714
715   if ((filter_te = OBJECT_GET_DATA(w, E_DFILTER_TE_KEY))) {
716     gtk_entry_set_text(GTK_ENTRY(filter_te), "");
717   }
718   main_filter_packets(&cfile, NULL, FALSE);
719 }
720
721 /* mark as reference time frame */
722 static void
723 set_frame_reftime(gboolean set, frame_data *frame, gint row) {
724   if (row == -1)
725     return;
726   if (set) {
727     frame->flags.ref_time=1;
728   } else {
729     frame->flags.ref_time=0;
730   }
731   cf_reftime_packets(&cfile);
732 }
733
734
735 GtkWidget *reftime_dialog = NULL;
736
737 static void reftime_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
738 {
739     switch(btn) {
740     case(ESD_BTN_YES):
741         timestamp_set_type(TS_RELATIVE);
742         recent.gui_time_format  = TS_RELATIVE;
743         cf_change_time_formats(&cfile);
744         break;
745     case(ESD_BTN_NO):
746         break;
747     default:
748         g_assert_not_reached();
749     }
750
751     if (cfile.current_frame) {
752       /* XXX hum, should better have a "cfile->current_row" here ... */
753       set_frame_reftime(!cfile.current_frame->flags.ref_time,
754                      cfile.current_frame,
755                      packet_list_find_row_from_data(cfile.current_frame));
756     }
757 }
758
759
760 void
761 reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
762 {
763
764   switch(action){
765   case REFTIME_TOGGLE:
766     if (cfile.current_frame) {
767         if(recent.gui_time_format != TS_RELATIVE && cfile.current_frame->flags.ref_time==0) {
768             reftime_dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO,
769                 PRIMARY_TEXT_START "Switch to the appropriate Time Display Format?" PRIMARY_TEXT_END "\n\n"
770                 "Time References don't work well with the currently selected Time Display Format.\n\n"
771                 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?");
772             simple_dialog_set_cb(reftime_dialog, reftime_answered_cb, NULL);
773         } else {
774             /* XXX hum, should better have a "cfile->current_row" here ... */
775             set_frame_reftime(!cfile.current_frame->flags.ref_time,
776                               cfile.current_frame,
777                               packet_list_find_row_from_data(cfile.current_frame));
778         }
779     }
780     break;
781   case REFTIME_FIND_NEXT:
782     find_previous_next_frame_with_filter("frame.ref_time", FALSE);
783     break;
784   case REFTIME_FIND_PREV:
785     find_previous_next_frame_with_filter("frame.ref_time", TRUE);
786     break;
787   }
788 }
789
790 void
791 find_next_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
792 {
793     find_previous_next_frame_with_filter("frame.marked == TRUE", FALSE);
794 }
795
796 void
797 find_prev_mark_cb(GtkWidget *w _U_, gpointer data _U_, int action _U_)
798 {
799     find_previous_next_frame_with_filter("frame.marked == TRUE", TRUE);
800 }
801
802 #if GTK_MAJOR_VERSION < 2
803 static void
804 tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_,
805                         gpointer user_data _U_)
806 #else
807 static void
808 tree_view_selection_changed_cb(GtkTreeSelection *sel, gpointer user_data _U_)
809 #endif
810 {
811     field_info   *finfo;
812     gchar        *help_str = NULL;
813     gchar         len_str[2+10+1+5+1]; /* ", {N} bytes\0",
814                                           N < 4294967296 */
815     gboolean      has_blurb = FALSE;
816     guint         length = 0, byte_len;
817     GtkWidget    *byte_view;
818     const guint8 *byte_data;
819     gint          finfo_length;
820 #if GTK_MAJOR_VERSION >= 2
821     GtkTreeModel *model;
822     GtkTreeIter   iter;
823 #endif
824
825 #if GTK_MAJOR_VERSION >= 2
826     /* if nothing is selected */
827     if (!gtk_tree_selection_get_selected(sel, &model, &iter))
828     {
829         /*
830          * Which byte view is displaying the current protocol tree
831          * row's data?
832          */
833         byte_view = get_notebook_bv_ptr(byte_nb_ptr);
834         if (byte_view == NULL)
835             return;     /* none */
836
837         byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
838         if (byte_data == NULL)
839             return;     /* none */
840
841         cf_unselect_field(&cfile);
842         packet_hex_print(byte_view, byte_data,
843                          cfile.current_frame, NULL, byte_len);
844         return;
845     }
846     gtk_tree_model_get(model, &iter, 1, &finfo, -1);
847 #else
848     g_assert(node);
849     finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
850 #endif
851     if (!finfo) return;
852
853     set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
854
855     byte_view = get_notebook_bv_ptr(byte_nb_ptr);
856     byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
857     g_assert(byte_data != NULL);
858
859     cfile.finfo_selected = finfo;
860     set_menus_for_selected_tree_row(&cfile);
861
862     if (finfo->hfinfo) {
863         if (finfo->hfinfo->blurb != NULL &&
864             finfo->hfinfo->blurb[0] != '\0') {
865             has_blurb = TRUE;
866             length = strlen(finfo->hfinfo->blurb);
867         } else {
868             length = strlen(finfo->hfinfo->name);
869         }
870         finfo_length = finfo->length + finfo->appendix_length;
871         if (finfo_length == 0) {
872             len_str[0] = '\0';
873         } else if (finfo_length == 1) {
874             strncpy (len_str, ", 1 byte", sizeof len_str);
875         } else {
876             g_snprintf (len_str, sizeof len_str, ", %d bytes", finfo_length);
877         }
878         statusbar_pop_field_msg();      /* get rid of current help msg */
879         if (length) {
880             help_str = g_strdup_printf(" %s (%s)%s",
881                     (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
882                     finfo->hfinfo->abbrev, len_str);
883             statusbar_push_field_msg(help_str);
884             g_free(help_str);
885         } else {
886             /*
887              * Don't show anything if the field name is zero-length;
888              * the pseudo-field for "proto_tree_add_text()" is such
889              * a field, and we don't want "Text (text)" showing up
890              * on the status line if you've selected such a field.
891              *
892              * XXX - there are zero-length fields for which we *do*
893              * want to show the field name.
894              *
895              * XXX - perhaps the name and abbrev field should be null
896              * pointers rather than null strings for that pseudo-field,
897              * but we'd have to add checks for null pointers in some
898              * places if we did that.
899              *
900              * Or perhaps protocol tree items added with
901              * "proto_tree_add_text()" should have -1 as the field index,
902              * with no pseudo-field being used, but that might also
903              * require special checks for -1 to be added.
904              */
905             statusbar_push_field_msg("");
906         }
907     }
908
909     packet_hex_print(byte_view, byte_data, cfile.current_frame, finfo,
910                      byte_len);
911 }
912
913 #if GTK_MAJOR_VERSION < 2
914 static void
915 tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_,
916                           gpointer user_data _U_)
917 {
918         GtkWidget       *byte_view;
919         const guint8    *data;
920         guint           len;
921
922         /*
923          * Which byte view is displaying the current protocol tree
924          * row's data?
925          */
926         byte_view = get_notebook_bv_ptr(byte_nb_ptr);
927         if (byte_view == NULL)
928                 return; /* none */
929
930         data = get_byte_view_data_and_length(byte_view, &len);
931         if (data == NULL)
932                 return; /* none */
933
934         cf_unselect_field(&cfile);
935         packet_hex_print(byte_view, data, cfile.current_frame, NULL, len);
936 }
937 #endif
938
939 void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
940   if (cfile.edt->tree)
941     collapse_all_tree(cfile.edt->tree, tree_view);
942 }
943
944 void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
945   if (cfile.edt->tree)
946     expand_all_tree(cfile.edt->tree, tree_view);
947 }
948
949 void expand_tree_cb(GtkWidget *widget _U_, gpointer data _U_) {
950 #if GTK_MAJOR_VERSION < 2
951   GtkCTreeNode *node;
952 #else
953   GtkTreePath  *path;
954 #endif
955
956 #if GTK_MAJOR_VERSION < 2
957   node = gtk_ctree_find_by_row_data(GTK_CTREE(tree_view), NULL, cfile.finfo_selected);
958   if(node) {
959     /* the mouse position is at an entry, expand that one */
960   gtk_ctree_expand_recursive(GTK_CTREE(tree_view), node);
961   }
962 #else
963   path = tree_find_by_field_info(GTK_TREE_VIEW(tree_view), cfile.finfo_selected);
964   if(path) {
965     /* the mouse position is at an entry, expand that one */
966   gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE);
967   gtk_tree_path_free(path);
968   }
969 #endif
970 }
971
972 void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
973   if (cfile.edt->tree) {
974     guint32 tmp = g_resolv_flags;
975     g_resolv_flags = RESOLV_ALL;
976     proto_tree_draw(cfile.edt->tree, tree_view);
977     g_resolv_flags = tmp;
978   }
979 }
980
981 /*
982  * Push a message referring to file access onto the statusbar.
983  */
984 void
985 statusbar_push_file_msg(const gchar *msg)
986 {
987     int i;
988
989     /*g_warning("statusbar_push: %s", msg);*/
990     for (i = STATUS_LEVEL_FILE + 1; i < NUM_STATUS_LEVELS; i++) {
991         if (status_levels[i])
992             return;
993     }
994     status_levels[STATUS_LEVEL_FILE]++;
995     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
996 }
997
998 /*
999  * Pop a message referring to file access off the statusbar.
1000  */
1001 void
1002 statusbar_pop_file_msg(void)
1003 {
1004     /*g_warning("statusbar_pop");*/
1005     if (status_levels[STATUS_LEVEL_FILE] > 0) {
1006         status_levels[STATUS_LEVEL_FILE]--;
1007     }
1008     gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1009 }
1010
1011 /*
1012  * XXX - do we need multiple statusbar contexts?
1013  */
1014
1015 /*
1016  * Push a message referring to the currently-selected field onto the statusbar.
1017  */
1018 void
1019 statusbar_push_field_msg(const gchar *msg)
1020 {
1021     int i;
1022
1023     for (i = STATUS_LEVEL_HELP + 1; i < NUM_STATUS_LEVELS; i++) {
1024         if (status_levels[i])
1025             return;
1026     }
1027     status_levels[STATUS_LEVEL_HELP]++;
1028
1029     gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
1030 }
1031
1032 /*
1033  * Pop a message referring to the currently-selected field off the statusbar.
1034  */
1035 void
1036 statusbar_pop_field_msg(void)
1037 {
1038     if (status_levels[STATUS_LEVEL_HELP] > 0) {
1039         status_levels[STATUS_LEVEL_HELP]--;
1040     }
1041     gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
1042 }
1043
1044 /*
1045  * Push a message referring to the current filter onto the statusbar.
1046  */
1047 void
1048 statusbar_push_filter_msg(const gchar *msg)
1049 {
1050     int i;
1051
1052     for (i = STATUS_LEVEL_FILTER + 1; i < NUM_STATUS_LEVELS; i++) {
1053         if (status_levels[i])
1054             return;
1055     }
1056     status_levels[STATUS_LEVEL_FILTER]++;
1057
1058     gtk_statusbar_push(GTK_STATUSBAR(info_bar), filter_ctx, msg);
1059 }
1060
1061 /*
1062  * Pop a message referring to the current filter off the statusbar.
1063  */
1064 void
1065 statusbar_pop_filter_msg(void)
1066 {
1067     if (status_levels[STATUS_LEVEL_FILTER] > 0) {
1068         status_levels[STATUS_LEVEL_FILTER]--;
1069     }
1070     gtk_statusbar_pop(GTK_STATUSBAR(info_bar), filter_ctx);
1071 }
1072
1073 /*
1074  * update the packets statusbar to the current values
1075  */
1076 void packets_bar_update(void)
1077 {
1078
1079     if(packets_bar) {
1080         /* remove old status */
1081         if(packets_str) {
1082             g_free(packets_str);
1083             gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1084         }
1085
1086         /* do we have any packets? */
1087         if(cfile.count) {
1088             if(cfile.drops_known) {
1089                 packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u Dropped: %u",
1090                     cfile.count, cfile.displayed_count, cfile.marked_count, cfile.drops);
1091             } else {
1092                 packets_str = g_strdup_printf(" Packets: %u Displayed: %u Marked: %u",
1093                     cfile.count, cfile.displayed_count, cfile.marked_count);
1094             }
1095         } else {
1096             packets_str = g_strdup(" No Packets");
1097         }
1098         gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, packets_str);
1099     }
1100 }
1101
1102 /*
1103  * update the packets statusbar to the current values
1104  */
1105 void profile_bar_update(void)
1106 {
1107     if (profile_bar) {
1108         /* remove old status */
1109         if(profile_str) {
1110             g_free(profile_str);
1111             gtk_statusbar_pop(GTK_STATUSBAR(profile_bar), profile_ctx);
1112         }
1113
1114         profile_str = g_strdup_printf (" Profile: %s", get_profile_name ());
1115
1116         gtk_statusbar_push(GTK_STATUSBAR(profile_bar), profile_ctx, profile_str);
1117     }
1118 }
1119
1120 void
1121 main_set_for_capture_file(gboolean have_capture_file_in)
1122 {
1123     have_capture_file = have_capture_file_in;
1124
1125     main_widgets_show_or_hide();
1126 }
1127
1128 gboolean
1129 main_do_quit(void)
1130 {
1131         /* get the current geometry, before writing it to disk */
1132         main_save_window_geometry(top_level);
1133
1134         /* write user's recent file to disk
1135          * It is no problem to write this file, even if we do not quit */
1136         write_recent();
1137
1138         /* XXX - should we check whether the capture file is an
1139            unsaved temporary file for a live capture and, if so,
1140            pop up a "do you want to exit without saving the capture
1141            file?" dialog, and then just return, leaving said dialog
1142            box to forcibly quit if the user clicks "OK"?
1143
1144            If so, note that this should be done in a subroutine that
1145            returns TRUE if we do so, and FALSE otherwise, and if it
1146            returns TRUE we should return TRUE without nuking anything.
1147
1148            Note that, if we do that, we might also want to check if
1149            an "Update list of packets in real time" capture is in
1150            progress and, if so, ask whether they want to terminate
1151            the capture and discard it, and return TRUE, before nuking
1152            any child capture, if they say they don't want to do so. */
1153
1154 #ifdef HAVE_LIBPCAP
1155         /* Nuke any child capture in progress. */
1156         capture_kill_child(capture_opts);
1157 #endif
1158
1159         /* Are we in the middle of reading a capture? */
1160         if (cfile.state == FILE_READ_IN_PROGRESS) {
1161                 /* Yes, so we can't just close the file and quit, as
1162                    that may yank the rug out from under the read in
1163                    progress; instead, just set the state to
1164                    "FILE_READ_ABORTED" and return - the code doing the read
1165                    will check for that and, if it sees that, will clean
1166                    up and quit. */
1167                 cfile.state = FILE_READ_ABORTED;
1168
1169                 /* Say that the window should *not* be deleted;
1170                    that'll be done by the code that cleans up. */
1171                 return TRUE;
1172         } else {
1173                 /* Close any capture file we have open; on some OSes, you
1174                    can't unlink a temporary capture file if you have it
1175                    open.
1176                    "cf_close()" will unlink it after closing it if
1177                    it's a temporary file.
1178
1179                    We do this here, rather than after the main loop returns,
1180                    as, after the main loop returns, the main window may have
1181                    been destroyed (if this is called due to a "destroy"
1182                    even on the main window rather than due to the user
1183                    selecting a menu item), and there may be a crash
1184                    or other problem when "cf_close()" tries to
1185                    clean up stuff in the main window.
1186
1187                    XXX - is there a better place to put this?
1188                    Or should we have a routine that *just* closes the
1189                    capture file, and doesn't do anything with the UI,
1190                    which we'd call here, and another routine that
1191                    calls that routine and also cleans up the UI, which
1192                    we'd call elsewhere? */
1193                 cf_close(&cfile);
1194
1195                 /* Exit by leaving the main loop, so that any quit functions
1196                    we registered get called. */
1197                 gtk_main_quit();
1198
1199                 /* Say that the window should be deleted. */
1200                 return FALSE;
1201         }
1202 }
1203
1204 static gboolean
1205 main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1206 {
1207   gpointer dialog;
1208
1209   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1210 #if GTK_MAJOR_VERSION >= 2
1211     gtk_window_present(GTK_WINDOW(top_level));
1212 #endif
1213     /* user didn't saved his current file, ask him */
1214     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1215                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1216                 "If you quit the program without saving, your capture data will be discarded.");
1217     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1218     return TRUE;
1219   } else {
1220     /* unchanged file, just exit */
1221     /* "main_do_quit()" indicates whether the main window should be deleted. */
1222     return main_do_quit();
1223   }
1224 }
1225
1226
1227
1228 static void
1229 main_load_window_geometry(GtkWidget *widget)
1230 {
1231     window_geometry_t geom;
1232
1233     geom.set_pos        = prefs.gui_geometry_save_position;
1234     geom.x              = recent.gui_geometry_main_x;
1235     geom.y              = recent.gui_geometry_main_y;
1236     geom.set_size       = prefs.gui_geometry_save_size;
1237     if (recent.gui_geometry_main_width > 0 &&
1238         recent.gui_geometry_main_height > 0) {
1239         geom.width          = recent.gui_geometry_main_width;
1240         geom.height         = recent.gui_geometry_main_height;
1241         geom.set_maximized  = prefs.gui_geometry_save_maximized;
1242     } else {
1243         /* We assume this means the width and height weren't set in
1244            the "recent" file (or that there is no "recent" file),
1245            and weren't set to a default value, so we don't set the
1246            size.  (The "recent" file code rejects non-positive width
1247            and height values.) */
1248        geom.set_size = FALSE;
1249     }
1250     geom.maximized      = recent.gui_geometry_main_maximized;
1251
1252     window_set_geometry(widget, &geom);
1253
1254     if (recent.has_gui_geometry_main_upper_pane && recent.gui_geometry_main_upper_pane)
1255         gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
1256     if (recent.has_gui_geometry_main_lower_pane && recent.gui_geometry_main_lower_pane)
1257         gtk_paned_set_position(GTK_PANED(main_second_pane), recent.gui_geometry_main_lower_pane);
1258     if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_left)
1259         gtk_paned_set_position(GTK_PANED(status_pane_left), recent.gui_geometry_status_pane_left);
1260     if (recent.has_gui_geometry_status_pane && recent.gui_geometry_status_pane_right)
1261         gtk_paned_set_position(GTK_PANED(status_pane_right), recent.gui_geometry_status_pane_right);
1262 }
1263
1264
1265 static void
1266 main_save_window_geometry(GtkWidget *widget)
1267 {
1268     window_geometry_t geom;
1269
1270     window_get_geometry(widget, &geom);
1271
1272     if (prefs.gui_geometry_save_position) {
1273         recent.gui_geometry_main_x = geom.x;
1274         recent.gui_geometry_main_y = geom.y;
1275     }
1276
1277     if (prefs.gui_geometry_save_size) {
1278         recent.gui_geometry_main_width  = geom.width;
1279         recent.gui_geometry_main_height = geom.height;
1280     }
1281
1282 #if GTK_MAJOR_VERSION >= 2
1283     if(prefs.gui_geometry_save_maximized) {
1284         recent.gui_geometry_main_maximized = geom.maximized;
1285     }
1286
1287     recent.gui_geometry_main_upper_pane     = gtk_paned_get_position(GTK_PANED(main_first_pane));
1288     recent.gui_geometry_main_lower_pane     = gtk_paned_get_position(GTK_PANED(main_second_pane));
1289     recent.gui_geometry_status_pane_left    = gtk_paned_get_position(GTK_PANED(status_pane_left));
1290     recent.gui_geometry_status_pane_right   = gtk_paned_get_position(GTK_PANED(status_pane_right));
1291 #endif
1292 }
1293
1294 static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1295 {
1296     switch(btn) {
1297     case(ESD_BTN_SAVE):
1298         /* save file first */
1299         file_save_as_cmd(after_save_exit, NULL);
1300         break;
1301     case(ESD_BTN_DONT_SAVE):
1302         main_do_quit();
1303         break;
1304     case(ESD_BTN_CANCEL):
1305         break;
1306     default:
1307         g_assert_not_reached();
1308     }
1309 }
1310
1311 void
1312 file_quit_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
1313 {
1314   gpointer dialog;
1315
1316   if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1317     /* user didn't saved his current file, ask him */
1318     dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1319                 PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
1320                 "If you quit the program without saving, your capture data will be discarded.");
1321     simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
1322   } else {
1323     /* unchanged file, just exit */
1324     main_do_quit();
1325   }
1326 }
1327
1328 static void
1329 print_usage(gboolean print_ver) {
1330
1331   FILE *output;
1332
1333 #ifdef _WIN32
1334   create_console();
1335 #endif
1336
1337   if (print_ver) {
1338     output = stdout;
1339     fprintf(output, "Wireshark " VERSION "%s\n"
1340         "Interactively dump and analyze network traffic.\n"
1341         "See http://www.wireshark.org for more information.\n"
1342         "\n"
1343         "%s",
1344         wireshark_svnversion, get_copyright_info());
1345   } else {
1346     output = stderr;
1347   }
1348   fprintf(output, "\n");
1349   fprintf(output, "Usage: wireshark [options] ... [ <infile> ]\n");
1350   fprintf(output, "\n");
1351
1352 #ifdef HAVE_LIBPCAP
1353   fprintf(output, "Capture interface:\n");
1354   fprintf(output, "  -i <interface>           name or idx of interface (def: first non-loopback)\n");
1355   fprintf(output, "  -f <capture filter>      packet filter in libpcap filter syntax\n");
1356   fprintf(output, "  -s <snaplen>             packet snapshot length (def: 65535)\n");
1357   fprintf(output, "  -p                       don't capture in promiscuous mode\n");
1358   fprintf(output, "  -k                       start capturing immediately (def: do nothing)\n");
1359   fprintf(output, "  -Q                       quit Wireshark after capturing\n");
1360   fprintf(output, "  -S                       update packet display when new packets are captured\n");
1361   fprintf(output, "  -l                       turn on automatic scrolling while -S is in use\n");
1362 #ifdef _WIN32
1363   fprintf(output, "  -B <buffer size>         size of kernel buffer (def: 1MB)\n");
1364 #endif
1365   fprintf(output, "  -y <link type>           link layer type (def: first appropriate)\n");
1366   fprintf(output, "  -D                       print list of interfaces and exit\n");
1367   fprintf(output, "  -L                       print list of link-layer types of iface and exit\n");
1368   fprintf(output, "\n");
1369   fprintf(output, "Capture stop conditions:\n");
1370   fprintf(output, "  -c <packet count>        stop after n packets (def: infinite)\n");
1371   fprintf(output, "  -a <autostop cond.> ...  duration:NUM - stop after NUM seconds\n");
1372   fprintf(output, "                           filesize:NUM - stop this file after NUM KB\n");
1373   fprintf(output, "                              files:NUM - stop after NUM files\n");
1374   /*fprintf(output, "\n");*/
1375   fprintf(output, "Capture output:\n");
1376   fprintf(output, "  -b <ringbuffer opt.> ... duration:NUM - switch to next file after NUM secs\n");
1377   fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
1378   fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
1379 #endif  /* HAVE_LIBPCAP */
1380
1381   /*fprintf(output, "\n");*/
1382   fprintf(output, "Input file:\n");
1383   fprintf(output, "  -r <infile>              set the filename to read from (no pipes or stdin!)\n");
1384
1385   fprintf(output, "\n");
1386   fprintf(output, "Processing:\n");
1387   fprintf(output, "  -R <read filter>         packet filter in Wireshark display filter syntax\n");
1388   fprintf(output, "  -n                       disable all name resolutions (def: all enabled)\n");
1389   fprintf(output, "  -N <name resolve flags>  enable specific name resolution(s): \"mntC\"\n");
1390
1391   fprintf(output, "\n");
1392   fprintf(output, "User interface:\n");
1393   fprintf(output, "  -C <config profile>      start with specified configuration profile\n");
1394   fprintf(output, "  -g <packet number>       go to specified packet number after \"-r\"\n");
1395   fprintf(output, "  -m <font>                set the font name used for most text\n");
1396   fprintf(output, "  -t ad|a|r|d|dd|e         output format of time stamps (def: r: rel. to first)\n");
1397   fprintf(output, "  -X <key>:<value>         eXtension options, see man page for details\n");
1398   fprintf(output, "  -z <statistics>          show various statistics, see man page for details\n");
1399
1400   fprintf(output, "\n");
1401   fprintf(output, "Output:\n");
1402   fprintf(output, "  -w <outfile|->           set the output filename (or '-' for stdout)\n");
1403
1404   fprintf(output, "\n");
1405   fprintf(output, "Miscellaneous:\n");
1406   fprintf(output, "  -h                       display this help and exit\n");
1407   fprintf(output, "  -v                       display version info and exit\n");
1408   fprintf(output, "  -P <key>:<path>          persconf:path - personal configuration files\n");
1409   fprintf(output, "                           persdata:path - personal data files\n");
1410   fprintf(output, "  -o <name>:<value> ...    override preference or recent setting\n");
1411 #ifndef _WIN32
1412   fprintf(output, "  --display=DISPLAY        X display to use\n");
1413 #endif
1414
1415 #ifdef _WIN32
1416   destroy_console();
1417 #endif
1418 }
1419
1420 static void
1421 show_version(void)
1422 {
1423 #ifdef _WIN32
1424   create_console();
1425 #endif
1426
1427   printf(PACKAGE " " VERSION "%s\n"
1428          "\n"
1429          "%s"
1430          "\n"
1431          "%s"
1432          "\n"
1433          "%s",
1434       wireshark_svnversion, get_copyright_info(), comp_info_str->str,
1435       runtime_info_str->str);
1436
1437 #ifdef _WIN32
1438   destroy_console();
1439 #endif
1440 }
1441
1442 /*
1443  * Report an error in command-line arguments.
1444  * Creates a console on Windows.
1445  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1446  * terminal isn't the standard error?
1447  */
1448 void
1449 cmdarg_err(const char *fmt, ...)
1450 {
1451   va_list ap;
1452
1453 #ifdef _WIN32
1454   create_console();
1455 #endif
1456   va_start(ap, fmt);
1457   fprintf(stderr, "wireshark: ");
1458   vfprintf(stderr, fmt, ap);
1459   fprintf(stderr, "\n");
1460   va_end(ap);
1461 }
1462
1463 /*
1464  * Report additional information for an error in command-line arguments.
1465  * Creates a console on Windows.
1466  * XXX - pop this up in a window of some sort on UNIX+X11 if the controlling
1467  * terminal isn't the standard error?
1468  */
1469 void
1470 cmdarg_err_cont(const char *fmt, ...)
1471 {
1472   va_list ap;
1473
1474 #ifdef _WIN32
1475   create_console();
1476 #endif
1477   va_start(ap, fmt);
1478   vfprintf(stderr, fmt, ap);
1479   fprintf(stderr, "\n");
1480   va_end(ap);
1481 }
1482
1483 #if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
1484 /*
1485    Once every 3 seconds we get a callback here which we use to update
1486    the tap extensions. Since Gtk1 is single threaded we dont have to
1487    worry about any locking or critical regions.
1488  */
1489 static gint
1490 update_cb(gpointer data _U_)
1491 {
1492         draw_tap_listeners(FALSE);
1493         return 1;
1494 }
1495 #else
1496
1497 /* if these three functions are copied to gtk1 Wireshark, since gtk1 does not
1498    use threads all updte_thread_mutex can be dropped and protect/unprotect
1499    would just be empty functions.
1500
1501    This allows gtk2-rpcstat.c and friends to be copied unmodified to
1502    gtk1-wireshark and it will just work.
1503  */
1504 static GStaticMutex update_thread_mutex = G_STATIC_MUTEX_INIT;
1505 gpointer
1506 update_thread(gpointer data _U_)
1507 {
1508     while(1){
1509         GTimeVal tv1, tv2;
1510         g_get_current_time(&tv1);
1511         g_static_mutex_lock(&update_thread_mutex);
1512         gdk_threads_enter();
1513         draw_tap_listeners(FALSE);
1514         gdk_threads_leave();
1515         g_static_mutex_unlock(&update_thread_mutex);
1516         g_thread_yield();
1517         g_get_current_time(&tv2);
1518         if( ((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) >
1519             (tv2.tv_sec * 1000000 + tv2.tv_usec) ){
1520             g_usleep(((tv1.tv_sec + 2) * 1000000 + tv1.tv_usec) -
1521                      (tv2.tv_sec * 1000000 + tv2.tv_usec));
1522         }
1523     }
1524     return NULL;
1525 }
1526 #endif
1527 void
1528 protect_thread_critical_region(void)
1529 {
1530 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1531     g_static_mutex_lock(&update_thread_mutex);
1532 #endif
1533 }
1534 void
1535 unprotect_thread_critical_region(void)
1536 {
1537 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
1538     g_static_mutex_unlock(&update_thread_mutex);
1539 #endif
1540 }
1541
1542 /* Set the file name in the status line, in the name for the main window,
1543    and in the name for the main window's icon. */
1544 static void
1545 set_display_filename(capture_file *cf)
1546 {
1547   const gchar *name_ptr;
1548   gchar       *status_msg;
1549   gchar       *size_str;
1550   gchar       *win_name;
1551
1552   name_ptr = cf_get_display_name(cf);
1553
1554   if (!cf->is_tempfile && cf->filename) {
1555     /* Add this filename to the list of recent files in the "Recent Files" submenu */
1556     add_menu_recent_capture_file(cf->filename);
1557   }
1558
1559   /* convert file size */
1560   if (cf->f_datalen/1024/1024 > 10) {
1561     size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d MB", cf->f_datalen/1024/1024);
1562   } else if (cf->f_datalen/1024 > 10) {
1563     size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d KB", cf->f_datalen/1024);
1564   } else {
1565     size_str = g_strdup_printf("%" G_GINT64_MODIFIER "d Bytes", cf->f_datalen);
1566   }
1567
1568   /* statusbar */
1569 #if 0
1570   /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1571   status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu [Expert: %s]",
1572     (cf->filename) ? cf->filename : "", size_str,
1573     (long)cf->elapsed_time.secs/3600,
1574     (long)cf->elapsed_time.secs%3600/60,
1575     (long)cf->elapsed_time.secs%60,
1576     val_to_str(expert_get_highest_severity(), expert_severity_vals, "Unknown (%u)"));
1577 #endif
1578   status_msg = g_strdup_printf(" File: \"%s\" %s %02lu:%02lu:%02lu",
1579     (cf->filename) ? cf->filename : "", size_str,
1580     (long)cf->elapsed_time.secs/3600,
1581     (long)cf->elapsed_time.secs%3600/60,
1582     (long)cf->elapsed_time.secs%60);
1583   g_free(size_str);
1584   statusbar_push_file_msg(status_msg);
1585   g_free(status_msg);
1586
1587   /* window title */
1588   win_name = g_strdup_printf("%s - Wireshark", name_ptr);
1589   set_main_window_name(win_name);
1590   g_free(win_name);
1591 }
1592
1593 GtkWidget           *close_dlg = NULL;
1594
1595 static void
1596 priv_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1597 {
1598     recent.privs_warn_if_elevated = !simple_dialog_check_get(dialog);
1599 }
1600
1601 #ifdef _WIN32
1602 static void
1603 npf_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
1604 {
1605     recent.privs_warn_if_no_npf = !simple_dialog_check_get(dialog);
1606 }
1607 #endif
1608
1609 static void
1610 main_cf_cb_file_closing(capture_file *cf)
1611 {
1612
1613     /* if we have more than 10000 packets, show a splash screen while closing */
1614     /* XXX - don't know a better way to decide wether to show or not,
1615      * as most of the time is spend in a single eth_clist_clear function,
1616      * so we can't use a progress bar here! */
1617     if(cf->count > 10000) {
1618         close_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE,
1619                                   "%sClosing file!%s\n\nPlease wait ...",
1620                                   simple_dialog_primary_start(),
1621                                   simple_dialog_primary_end());
1622 #if GTK_MAJOR_VERSION >= 2
1623         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
1624 #else
1625         gtk_window_set_position(GTK_WINDOW(close_dlg), GTK_WIN_POS_CENTER);
1626 #endif
1627     }
1628
1629     /* Destroy all windows, which refer to the
1630        capture file we're closing. */
1631     destroy_packet_wins();
1632     file_save_as_destroy();
1633
1634     /* Clear any file-related status bar messages.
1635        XXX - should be "clear *ALL* file-related status bar messages;
1636        will there ever be more than one on the stack? */
1637     statusbar_pop_file_msg();
1638
1639     /* Restore the standard title bar message. */
1640     set_main_window_name("The Wireshark Network Analyzer");
1641
1642     /* Disable all menu items that make sense only if you have a capture. */
1643     set_menus_for_capture_file(NULL);
1644     set_menus_for_captured_packets(FALSE);
1645     set_menus_for_selected_packet(cf);
1646     set_menus_for_capture_in_progress(FALSE);
1647     set_menus_for_selected_tree_row(cf);
1648
1649     /* Set up main window for no capture file. */
1650     main_set_for_capture_file(FALSE);
1651
1652     main_window_update();
1653 }
1654
1655 static void
1656 main_cf_cb_file_closed(capture_file *cf _U_)
1657 {
1658   if(close_dlg != NULL) {
1659     splash_destroy(close_dlg);
1660     close_dlg = NULL;
1661   }
1662
1663   /* go back to "No packets" */
1664   packets_bar_update();
1665 }
1666
1667 static void
1668 main_cf_cb_file_read_start(capture_file *cf)
1669 {
1670   const gchar *name_ptr;
1671   gchar       *load_msg;
1672
1673   /* Ensure we pop any previous loaded filename */
1674   statusbar_pop_file_msg();
1675
1676   name_ptr = get_basename(cf->filename);
1677
1678   load_msg = g_strdup_printf(" Loading: %s", name_ptr);
1679   statusbar_push_file_msg(load_msg);
1680   g_free(load_msg);
1681
1682   /* Set up main window for a capture file. */
1683   main_set_for_capture_file(TRUE);
1684 }
1685
1686 static void
1687 main_cf_cb_file_read_finished(capture_file *cf)
1688 {
1689     statusbar_pop_file_msg();
1690     set_display_filename(cf);
1691
1692     /* Enable menu items that make sense if you have a capture file you've
1693        finished reading. */
1694     set_menus_for_capture_file(cf);
1695
1696     /* Enable menu items that make sense if you have some captured packets. */
1697     set_menus_for_captured_packets(TRUE);
1698 }
1699
1700 #if GTK_MAJOR_VERSION >= 2
1701 GList *icon_list_create(
1702     const char **icon16_xpm,
1703     const char **icon32_xpm,
1704     const char **icon48_xpm,
1705     const char **icon64_xpm)
1706 {
1707   GList *icon_list = NULL;
1708   GdkPixbuf * pixbuf16;
1709   GdkPixbuf * pixbuf32;
1710   GdkPixbuf * pixbuf48;
1711   GdkPixbuf * pixbuf64;
1712
1713
1714   if(icon16_xpm != NULL) {
1715       pixbuf16 = gdk_pixbuf_new_from_xpm_data(icon16_xpm);
1716       g_assert(pixbuf16);
1717       icon_list = g_list_append(icon_list, pixbuf16);
1718   }
1719
1720   if(icon32_xpm != NULL) {
1721       pixbuf32 = gdk_pixbuf_new_from_xpm_data(icon32_xpm);
1722       g_assert(pixbuf32);
1723       icon_list = g_list_append(icon_list, pixbuf32);
1724   }
1725
1726   if(icon48_xpm != NULL) {
1727       pixbuf48 = gdk_pixbuf_new_from_xpm_data(icon48_xpm);
1728       g_assert(pixbuf48);
1729       icon_list = g_list_append(icon_list, pixbuf48);
1730   }
1731
1732   if(icon64_xpm != NULL) {
1733       pixbuf64 = gdk_pixbuf_new_from_xpm_data(icon64_xpm);
1734       g_assert(pixbuf64);
1735       icon_list = g_list_append(icon_list, pixbuf64);
1736   }
1737
1738   return icon_list;
1739 }
1740 #endif
1741
1742 #ifdef HAVE_LIBPCAP
1743 static void
1744 main_cf_cb_live_capture_prepared(capture_options *capture_opts)
1745 {
1746     gchar *title;
1747 #if GTK_MAJOR_VERSION >= 2
1748     static GList *icon_list = NULL;
1749 #endif
1750
1751
1752     if(capture_opts->iface) {
1753         title = g_strdup_printf("%s: Capturing - Wireshark",
1754                                 get_iface_description(capture_opts));
1755     } else {
1756         title = g_strdup_printf("Capturing - Wireshark");
1757     }
1758     set_main_window_name(title);
1759     g_free(title);
1760
1761 #if GTK_MAJOR_VERSION >= 2
1762     if(icon_list == NULL) {
1763         icon_list = icon_list_create(wsiconcap16_xpm, wsiconcap32_xpm, wsiconcap48_xpm, NULL);
1764     }
1765     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1766 #endif
1767
1768     /* Disable menu items that make no sense if you're currently running
1769        a capture. */
1770     set_menus_for_capture_in_progress(TRUE);
1771
1772     /* update statusbar */
1773     statusbar_push_file_msg(" Waiting for capture input data ...");
1774
1775     /* Don't set up main window for a capture file. */
1776     main_set_for_capture_file(FALSE);
1777 }
1778
1779 static void
1780 main_cf_cb_live_capture_update_started(capture_options *capture_opts)
1781 {
1782     gchar *capture_msg;
1783     gchar *title;
1784
1785     /* We've done this in "prepared" above, but it will be cleared while
1786        switching to the next multiple file. */
1787     if(capture_opts->iface) {
1788         title = g_strdup_printf("%s: Capturing - Wireshark",
1789                                 get_iface_description(capture_opts));
1790     } else {
1791         title = g_strdup_printf("Capturing - Wireshark");
1792     }
1793     set_main_window_name(title);
1794     g_free(title);
1795
1796     set_menus_for_capture_in_progress(TRUE);
1797
1798     /* Enable menu items that make sense if you have some captured
1799        packets (yes, I know, we don't have any *yet*). */
1800     set_menus_for_captured_packets(TRUE);
1801
1802     statusbar_pop_file_msg();
1803
1804     if(capture_opts->iface) {
1805         capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1806                                       get_iface_description(capture_opts),
1807                                       (capture_opts->save_file) ? capture_opts->save_file : "");
1808     } else {
1809         capture_msg = g_strdup_printf(" <live capture in progress> to file: %s",
1810             (capture_opts->save_file) ? capture_opts->save_file : "");
1811     }
1812
1813     statusbar_push_file_msg(capture_msg);
1814
1815     g_free(capture_msg);
1816
1817     /* Set up main window for a capture file. */
1818     main_set_for_capture_file(TRUE);
1819 }
1820
1821 static void
1822 main_cf_cb_live_capture_update_continue(capture_file *cf)
1823 {
1824     gchar *capture_msg;
1825
1826
1827     statusbar_pop_file_msg();
1828
1829 #if 0
1830     /* XXX - don't show the highest expert level unless the TCP checksum offloading is "solved" */
1831     if (cf->f_datalen/1024/1024 > 10) {
1832         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d MB [Expert: %s]",
1833                                       get_iface_description(capture_opts),
1834                                       capture_opts->save_file,
1835                                       cf->f_datalen/1024/1024,
1836                                       val_to_str(expert_get_highest_severity(),
1837                                                  expert_severity_vals,
1838                                                  "Unknown (%u)"));
1839     } else if (cf->f_datalen/1024 > 10) {
1840         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d KB [Expert: %s]",
1841                                       get_iface_description(capture_opts),
1842                                       capture_opts->save_file,
1843                                       cf->f_datalen/1024,
1844                                       val_to_str(expert_get_highest_severity(),
1845                                                  expert_severity_vals,
1846                                                  "Unknown (%u)"));
1847     } else {
1848         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d Bytes [Expert: %s]",
1849                                       get_iface_description(capture_opts),
1850                                       capture_opts->save_file,
1851                                       cf->f_datalen,
1852                                       val_to_str(expert_get_highest_severity(),
1853                                                  expert_severity_vals,
1854                                                  "Unknown (%u)"));
1855     }
1856 #endif
1857     if (cf->f_datalen/1024/1024 > 10) {
1858         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d MB",
1859                                       get_iface_description(capture_opts),
1860                                       capture_opts->save_file,
1861                                       cf->f_datalen/1024/1024);
1862     } else if (cf->f_datalen/1024 > 10) {
1863         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d KB",
1864                                       get_iface_description(capture_opts),
1865                                       capture_opts->save_file,
1866                                       cf->f_datalen/1024);
1867     } else {
1868         capture_msg = g_strdup_printf(" %s: <live capture in progress> File: %s %" G_GINT64_MODIFIER "d Bytes",
1869                                       get_iface_description(capture_opts),
1870                                       capture_opts->save_file,
1871                                       cf->f_datalen);
1872     }
1873
1874     statusbar_push_file_msg(capture_msg);
1875 }
1876
1877 GtkWidget * stop_dlg = NULL;
1878
1879 static void
1880 main_cf_cb_live_capture_update_finished(capture_file *cf)
1881 {
1882 #if GTK_MAJOR_VERSION >= 2
1883     static GList *icon_list = NULL;
1884 #endif
1885
1886     if(stop_dlg != NULL) {
1887         simple_dialog_close(stop_dlg);
1888         stop_dlg = NULL;
1889     }
1890
1891     /* Pop the "<live capture in progress>" message off the status bar. */
1892     statusbar_pop_file_msg();
1893
1894     set_display_filename(cf);
1895
1896     /* Enable menu items that make sense if you're not currently running
1897      a capture. */
1898     set_menus_for_capture_in_progress(FALSE);
1899
1900     /* Enable menu items that make sense if you have a capture file
1901        you've finished reading. */
1902     set_menus_for_capture_file(cf);
1903
1904     /* Set up main window for a capture file. */
1905     main_set_for_capture_file(TRUE);
1906
1907 #if GTK_MAJOR_VERSION >= 2
1908     if(icon_list == NULL) {
1909         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1910     }
1911     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1912 #endif
1913
1914     if(capture_opts->quit_after_cap) {
1915         /* command line asked us to quit after the capture */
1916         /* don't pop up a dialog to ask for unsaved files etc. */
1917         main_do_quit();
1918     }
1919 }
1920
1921 static void
1922 main_cf_cb_live_capture_fixed_started(capture_options *capture_opts)
1923 {
1924     gchar *capture_msg;
1925
1926
1927     /* Enable menu items that make sense if you have some captured
1928        packets (yes, I know, we don't have any *yet*). */
1929     /*set_menus_for_captured_packets(TRUE);*/
1930
1931     statusbar_pop_file_msg();
1932
1933     capture_msg = g_strdup_printf(" %s: <live capture in progress> to file: %s",
1934                                   get_iface_description(capture_opts),
1935                                   (capture_opts->save_file) ? capture_opts->save_file : "");
1936
1937     statusbar_push_file_msg(capture_msg);
1938     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, " Packets: 0");
1939
1940     g_free(capture_msg);
1941
1942     /* Don't set up main window for a capture file. */
1943     main_set_for_capture_file(FALSE);
1944 }
1945
1946 static void
1947 main_cf_cb_live_capture_fixed_continue(capture_file *cf)
1948 {
1949     gchar *capture_msg;
1950
1951
1952     gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1953
1954     capture_msg = g_strdup_printf(" Packets: %u", cf_get_packet_count(cf));
1955
1956     gtk_statusbar_push(GTK_STATUSBAR(packets_bar), packets_ctx, capture_msg);
1957
1958     g_free(capture_msg);
1959 }
1960
1961 static void
1962 main_cf_cb_live_capture_fixed_finished(capture_file *cf _U_)
1963 {
1964 #if GTK_MAJOR_VERSION >= 2
1965     static GList *icon_list = NULL;
1966 #endif
1967
1968     if(stop_dlg != NULL) {
1969         simple_dialog_close(stop_dlg);
1970         stop_dlg = NULL;
1971     }
1972
1973     /* Pop the "<live capture in progress>" message off the status bar. */
1974     statusbar_pop_file_msg();
1975
1976     /* Pop the "<capturing>" message off the status bar */
1977     gtk_statusbar_pop(GTK_STATUSBAR(packets_bar), packets_ctx);
1978
1979     /*set_display_filename(cf);*/
1980
1981     /* Enable menu items that make sense if you're not currently running
1982      a capture. */
1983     set_menus_for_capture_in_progress(FALSE);
1984
1985     /* Restore the standard title bar message */
1986     /* (just in case we have trouble opening the capture file). */
1987     set_main_window_name("The Wireshark Network Analyzer");
1988
1989 #if GTK_MAJOR_VERSION >= 2
1990     if(icon_list == NULL) {
1991         icon_list = icon_list_create(wsicon16_xpm, wsicon32_xpm, wsicon48_xpm, wsicon64_xpm);
1992     }
1993     gtk_window_set_icon_list(GTK_WINDOW(top_level), icon_list);
1994 #endif
1995
1996     /* We don't have loaded the capture file, this will be done later.
1997      * For now we still have simply a blank screen. */
1998
1999     if(capture_opts->quit_after_cap) {
2000         /* command line asked us to quit after the capture */
2001         /* don't pop up a dialog to ask for unsaved files etc. */
2002         main_do_quit();
2003     }
2004 }
2005
2006 static void
2007 main_cf_cb_live_capture_stopping(capture_file *cf _U_)
2008 {
2009     /* Beware: this state won't be called, if the capture child
2010      * closes the capturing on it's own! */
2011 #if 0
2012     /* XXX - the time to stop the capture has been reduced (this was only a
2013      * problem on Win32 because of the capture piping), so showing a splash
2014      * isn't really necessary any longer. Unfortunately, the GTKClist packet
2015      * list seems to have problems updating after the dialog is closed, so
2016      * this was disabled here. */
2017     stop_dlg = simple_dialog(ESD_TYPE_STOP, ESD_BTN_NONE, "%sCapture stop!%s\n\nPlease wait ...",
2018                 simple_dialog_primary_start(), simple_dialog_primary_end());
2019 #if GTK_MAJOR_VERSION >= 2
2020     gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER_ON_PARENT);
2021 #else
2022     gtk_window_set_position(GTK_WINDOW(stop_dlg), GTK_WIN_POS_CENTER);
2023 #endif
2024 #endif
2025 }
2026
2027 #endif
2028
2029 static void
2030 main_cf_cb_packet_selected(gpointer data)
2031 {
2032     capture_file *cf = data;
2033
2034     /* Display the GUI protocol tree and hex dump.
2035       XXX - why do we dump core if we call "proto_tree_draw()"
2036       before calling "add_byte_views()"? */
2037     add_main_byte_views(cf->edt);
2038     main_proto_tree_draw(cf->edt->tree);
2039
2040     /* The user is searching for a string in the data or a hex value,
2041      * highlight the field that is found in the tree and hex displays. */
2042     if((cfile.string || cfile.hex) && cfile.search_pos != 0) {
2043 #if GTK_MAJOR_VERSION < 2
2044         highlight_field(cf->edt->tvb, cfile.search_pos,
2045                         (GtkCTree *)tree_view, cf->edt->tree);
2046 #else
2047         highlight_field(cf->edt->tvb, cfile.search_pos,
2048                         (GtkTreeView *)tree_view, cf->edt->tree);
2049 #endif
2050         cfile.search_pos = 0; /* Reset the position */
2051     }
2052
2053     /* A packet is selected. */
2054     set_menus_for_selected_packet(cf);
2055 }
2056
2057 static void
2058 main_cf_cb_packet_unselected(capture_file *cf)
2059 {
2060     /* Clear out the display of that packet. */
2061     clear_tree_and_hex_views();
2062
2063     /* No packet is selected. */
2064     set_menus_for_selected_packet(cf);
2065 }
2066
2067 static void
2068 main_cf_cb_field_unselected(capture_file *cf)
2069 {
2070     statusbar_pop_field_msg();
2071     set_menus_for_selected_tree_row(cf);
2072 }
2073
2074 static void
2075 main_cf_cb_file_safe_started(gchar * filename)
2076 {
2077     const gchar  *name_ptr;
2078     gchar        *save_msg;
2079
2080     name_ptr = get_basename(filename);
2081
2082     save_msg = g_strdup_printf(" Saving: %s...", name_ptr);
2083
2084     statusbar_push_file_msg(save_msg);
2085     g_free(save_msg);
2086 }
2087
2088 static void
2089 main_cf_cb_file_safe_finished(gpointer data _U_)
2090 {
2091     /* Pop the "Saving:" message off the status bar. */
2092     statusbar_pop_file_msg();
2093 }
2094
2095 static void
2096 main_cf_cb_file_safe_failed(gpointer data _U_)
2097 {
2098     /* Pop the "Saving:" message off the status bar. */
2099     statusbar_pop_file_msg();
2100 }
2101
2102 static void
2103 main_cf_cb_file_safe_reload_finished(gpointer data _U_)
2104 {
2105     set_menus_for_capture_file(&cfile);
2106 }
2107
2108 static void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
2109 {
2110     switch(event) {
2111     case(cf_cb_file_closing):
2112         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closing");
2113         main_cf_cb_file_closing(data);
2114         break;
2115     case(cf_cb_file_closed):
2116         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Closed");
2117         main_cf_cb_file_closed(data);
2118         break;
2119     case(cf_cb_file_read_start):
2120         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read start");
2121         main_cf_cb_file_read_start(data);
2122         break;
2123     case(cf_cb_file_read_finished):
2124         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: Read finished");
2125         main_cf_cb_file_read_finished(data);
2126         break;
2127 #ifdef HAVE_LIBPCAP
2128     case(cf_cb_live_capture_prepared):
2129         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture prepared");
2130         main_cf_cb_live_capture_prepared(data);
2131         break;
2132     case(cf_cb_live_capture_update_started):
2133         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update started");
2134         main_cf_cb_live_capture_update_started(data);
2135         break;
2136     case(cf_cb_live_capture_update_continue):
2137         /*g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update continue");*/
2138         main_cf_cb_live_capture_update_continue(data);
2139         break;
2140     case(cf_cb_live_capture_update_finished):
2141         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture update finished");
2142         main_cf_cb_live_capture_update_finished(data);
2143         break;
2144     case(cf_cb_live_capture_fixed_started):
2145         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed started");
2146         main_cf_cb_live_capture_fixed_started(data);
2147         break;
2148     case(cf_cb_live_capture_fixed_continue):
2149         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed continue");
2150         main_cf_cb_live_capture_fixed_continue(data);
2151         break;
2152     case(cf_cb_live_capture_fixed_finished):
2153         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture fixed finished");
2154         main_cf_cb_live_capture_fixed_finished(data);
2155         break;
2156     case(cf_cb_live_capture_stopping):
2157         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: capture stopping");
2158         main_cf_cb_live_capture_stopping(data);
2159         break;
2160 #endif
2161     case(cf_cb_packet_selected):
2162         main_cf_cb_packet_selected(data);
2163         break;
2164     case(cf_cb_packet_unselected):
2165         main_cf_cb_packet_unselected(data);
2166         break;
2167     case(cf_cb_field_unselected):
2168         main_cf_cb_field_unselected(data);
2169         break;
2170     case(cf_cb_file_safe_started):
2171         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe started");
2172         main_cf_cb_file_safe_started(data);
2173         break;
2174     case(cf_cb_file_safe_finished):
2175         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe finished");
2176         main_cf_cb_file_safe_finished(data);
2177         break;
2178     case(cf_cb_file_safe_reload_finished):
2179         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: reload finished");
2180         main_cf_cb_file_safe_reload_finished(data);
2181         break;
2182     case(cf_cb_file_safe_failed):
2183         g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_DEBUG, "Callback: safe failed");
2184         main_cf_cb_file_safe_failed(data);
2185         break;
2186     default:
2187         g_warning("main_cf_callback: event %u unknown", event);
2188         g_assert_not_reached();
2189     }
2190 }
2191
2192 static void
2193 get_gui_compiled_info(GString *str)
2194 {
2195   get_epan_compiled_version_info(str);
2196
2197   g_string_append(str, ", ");
2198 #ifdef HAVE_LIBPORTAUDIO
2199 #ifdef PORTAUDIO_API_1
2200   g_string_append(str, "with PortAudio <= V18");
2201 #else /* PORTAUDIO_API_1 */
2202   g_string_append(str, "with ");
2203   g_string_append(str, Pa_GetVersionText());
2204 #endif /* PORTAUDIO_API_1 */
2205 #else /* HAVE_LIBPORTAUDIO */
2206   g_string_append(str, "without PortAudio");
2207 #endif /* HAVE_LIBPORTAUDIO */
2208
2209   g_string_append(str, ", ");
2210 #ifdef HAVE_AIRPCAP
2211   get_compiled_airpcap_version(str);
2212 #else
2213   g_string_append(str, "without AirPcap");
2214 #endif
2215 }
2216
2217 static void
2218 get_gui_runtime_info(GString *str
2219 #ifndef HAVE_AIRPCAP
2220         _U_
2221 #endif
2222 )
2223 {
2224 #ifdef HAVE_AIRPCAP
2225   g_string_append(str, ", ");
2226   get_runtime_airpcap_version(str);
2227 #endif
2228
2229   if(u3_active()) {
2230     g_string_append(str, ", ");
2231     u3_runtime_info(str);
2232   }
2233
2234 }
2235
2236 static e_prefs *
2237 read_configuration_files(char **gdp_path, char **dp_path)
2238 {
2239   int                  gpf_open_errno, gpf_read_errno;
2240   int                  cf_open_errno, df_open_errno;
2241   int                  gdp_open_errno, gdp_read_errno;
2242   int                  dp_open_errno, dp_read_errno;
2243   char                *gpf_path, *pf_path;
2244   char                *cf_path, *df_path;
2245   int                  pf_open_errno, pf_read_errno;
2246   e_prefs             *prefs;
2247
2248   /* Read the preference files. */
2249   prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
2250                      &pf_open_errno, &pf_read_errno, &pf_path);
2251
2252   if (gpf_path != NULL) {
2253     if (gpf_open_errno != 0) {
2254       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2255         "Could not open global preferences file\n\"%s\": %s.", gpf_path,
2256         strerror(gpf_open_errno));
2257     }
2258     if (gpf_read_errno != 0) {
2259       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2260         "I/O error reading global preferences file\n\"%s\": %s.", gpf_path,
2261         strerror(gpf_read_errno));
2262     }
2263   }
2264   if (pf_path != NULL) {
2265     if (pf_open_errno != 0) {
2266       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2267         "Could not open your preferences file\n\"%s\": %s.", pf_path,
2268         strerror(pf_open_errno));
2269     }
2270     if (pf_read_errno != 0) {
2271       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2272         "I/O error reading your preferences file\n\"%s\": %s.", pf_path,
2273         strerror(pf_read_errno));
2274     }
2275     g_free(pf_path);
2276     pf_path = NULL;
2277   }
2278
2279 #ifdef _WIN32
2280   /* if the user wants a console to be always there, well, we should open one for him */
2281   if (prefs->gui_console_open == console_open_always) {
2282     create_console();
2283   }
2284 #endif
2285
2286   /* Read the capture filter file. */
2287   read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
2288   if (cf_path != NULL) {
2289       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2290         "Could not open your capture filter file\n\"%s\": %s.", cf_path,
2291         strerror(cf_open_errno));
2292       g_free(cf_path);
2293   }
2294
2295   /* Read the display filter file. */
2296   read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
2297   if (df_path != NULL) {
2298       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2299         "Could not open your display filter file\n\"%s\": %s.", df_path,
2300         strerror(df_open_errno));
2301       g_free(df_path);
2302   }
2303
2304   /* Read the disabled protocols file. */
2305   read_disabled_protos_list(gdp_path, &gdp_open_errno, &gdp_read_errno,
2306                             dp_path, &dp_open_errno, &dp_read_errno);
2307   if (*gdp_path != NULL) {
2308     if (gdp_open_errno != 0) {
2309       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2310         "Could not open global disabled protocols file\n\"%s\": %s.",
2311         *gdp_path, strerror(gdp_open_errno));
2312     }
2313     if (gdp_read_errno != 0) {
2314       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2315         "I/O error reading global disabled protocols file\n\"%s\": %s.",
2316         *gdp_path, strerror(gdp_read_errno));
2317     }
2318     g_free(*gdp_path);
2319     *gdp_path = NULL;
2320   }
2321   if (*dp_path != NULL) {
2322     if (dp_open_errno != 0) {
2323       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2324         "Could not open your disabled protocols file\n\"%s\": %s.", *dp_path,
2325         strerror(dp_open_errno));
2326     }
2327     if (dp_read_errno != 0) {
2328       simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2329         "I/O error reading your disabled protocols file\n\"%s\": %s.", *dp_path,
2330         strerror(dp_read_errno));
2331     }
2332     g_free(*dp_path);
2333     *dp_path = NULL;
2334   }
2335
2336   return prefs;
2337 }
2338
2339 /* And now our feature presentation... [ fade to music ] */
2340 int
2341 main(int argc, char *argv[])
2342 {
2343   char                *init_progfile_dir_error;
2344   char                *s;
2345   int                  opt;
2346   extern char         *optarg;
2347   gboolean             arg_error = FALSE;
2348
2349 #ifdef _WIN32
2350   WSADATA              wsaData;
2351 #endif  /* _WIN32 */
2352
2353   char                *rf_path;
2354   int                  rf_open_errno;
2355   char                *gdp_path, *dp_path;
2356   int                  err;
2357 #ifdef HAVE_LIBPCAP
2358   gboolean             start_capture = FALSE;
2359 #else
2360   gboolean             capture_option_specified = FALSE;
2361 #endif
2362   gint                 pl_size = 280, tv_size = 95, bv_size = 75;
2363   gchar               *rc_file, *cf_name = NULL, *rfilter = NULL;
2364   dfilter_t           *rfcode = NULL;
2365   gboolean             rfilter_parse_failed = FALSE;
2366   e_prefs             *prefs;
2367   char                 badopt;
2368   GtkWidget           *splash_win = NULL;
2369   GLogLevelFlags       log_flags;
2370   guint                go_to_packet = 0;
2371   int                  optind_initial;
2372   int                  status;
2373   gchar               *cur_user, *cur_group;
2374
2375 #ifdef HAVE_AIRPCAP
2376   char                  *err_str;
2377   /*gchar                       *cant_get_if_list_errstr;*/
2378 #endif
2379
2380 #define OPTSTRING_INIT "a:b:c:C:Df:g:Hhi:klLm:nN:o:P:pQr:R:Ss:t:vw:X:y:z:"
2381
2382 #if defined HAVE_LIBPCAP && defined _WIN32
2383 #define OPTSTRING_WIN32 "B:"
2384 #else
2385 #define OPTSTRING_WIN32 ""
2386 #endif
2387
2388   char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] =
2389     OPTSTRING_INIT OPTSTRING_WIN32;
2390
2391   /*
2392    * Get credential information for later use, and drop privileges
2393    * before doing anything else.
2394    * Let the user know if anything happened.
2395    */
2396   get_credential_info();
2397   relinquish_special_privs_perm();
2398
2399   /*
2400    * Attempt to get the pathname of the executable file.
2401    */
2402   init_progfile_dir_error = init_progfile_dir(argv[0]);
2403
2404   /* initialize the funnel mini-api */
2405   initialize_funnel_ops();
2406
2407 #ifdef  HAVE_AIRPDCAP
2408   /*    Davide Schiera (2006-11-18): init AirPDcap context                                                              */
2409   AirPDcapInitContext(&airpdcap_ctx);
2410   /* Davide Schiera (2006-11-18) -------------------------------------------    */
2411 #endif
2412
2413 #ifdef _WIN32
2414   /* Load wpcap if possible. Do this before collecting the run-time version information */
2415   load_wpcap();
2416
2417   /* ... and also load the packet.dll from wpcap */
2418   wpcap_packet_load();
2419
2420 #ifdef HAVE_AIRPCAP
2421   /* Load the airpcap.dll.  This must also be done before collecting
2422    * run-time version information. */
2423   airpcap_dll_ret_val = load_airpcap();
2424
2425   switch (airpcap_dll_ret_val) {
2426   case AIRPCAP_DLL_OK:
2427     /* load the airpcap interfaces */
2428     airpcap_if_list = get_airpcap_interface_list(&err, &err_str);
2429
2430     if (airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0){
2431       if (err == CANT_GET_AIRPCAP_INTERFACE_LIST && err_str != NULL) {
2432         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s", "Failed to open Airpcap Adapters!");
2433         g_free(err_str);
2434       }
2435       airpcap_if_active = NULL;
2436
2437     } else {
2438
2439       /* select the first ad default (THIS SHOULD BE CHANGED) */
2440       airpcap_if_active = airpcap_get_default_if(airpcap_if_list);
2441           }
2442     break;
2443 #if 0
2444     /*
2445      * XXX - Maybe we need to warn the user if one of the following happens???
2446      */
2447     case AIRPCAP_DLL_OLD:
2448       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_OLD\n");
2449       break;
2450
2451     case AIRPCAP_DLL_ERROR:
2452       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
2453       break;
2454
2455     case AIRPCAP_DLL_NOT_FOUND:
2456       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
2457       break;
2458 #endif
2459   }
2460 #endif /* HAVE_AIRPCAP */
2461
2462   /* Start windows sockets */
2463   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
2464 #endif  /* _WIN32 */
2465
2466   /* Assemble the compile-time version information string */
2467   comp_info_str = g_string_new("Compiled ");
2468
2469   g_string_append(comp_info_str, "with ");
2470   g_string_sprintfa(comp_info_str,
2471 #ifdef GTK_MAJOR_VERSION
2472                     "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
2473                     GTK_MICRO_VERSION);
2474 #else
2475                     "GTK+ (version unknown)");
2476 #endif
2477   g_string_append(comp_info_str, ", ");
2478
2479   get_compiled_version_info(comp_info_str, get_gui_compiled_info);
2480
2481   /* Assemble the run-time version information string */
2482   runtime_info_str = g_string_new("Running ");
2483   get_runtime_version_info(runtime_info_str, get_gui_runtime_info);
2484
2485
2486   /* "pre-scan" the command line parameters, if we have "console only"
2487      parameters.  We do this so we don't start GTK+ if we're only showing
2488      command-line help or version information.
2489
2490      XXX - this pre-scan is doen before we start GTK+, so we haven't
2491      run gtk_init() on the arguments.  That means that GTK+ arguments
2492      have not been removed from the argument list; those arguments
2493      begin with "--", and will be treated as an error by getopt().
2494
2495      We thus ignore errors - *and* set "opterr" to 0 to suppress the
2496      error messages. */
2497   opterr = 0;
2498   optind_initial = optind;
2499   while ((opt = getopt(argc, argv, optstring)) != -1) {
2500     switch (opt) {
2501       case 'C':        /* Configuration Profile */
2502         if (profile_exists (optarg)) {
2503           set_profile_name (optarg);
2504         } else {
2505           cmdarg_err("Configuration Profile \"%s\" does not exist", optarg);
2506           exit(1);
2507         }
2508         break;
2509       case 'h':        /* Print help and exit */
2510         print_usage(TRUE);
2511         exit(0);
2512         break;
2513       case 'P':        /* Path settings - change these before the Preferences and alike are processed */
2514         status = filesystem_opt(opt, optarg);
2515         if(status != 0) {
2516             cmdarg_err("-P flag \"%s\" failed (hint: is it quoted and existing?)", optarg);
2517             exit(status);
2518         }
2519         break;
2520       case 'v':        /* Show version and exit */
2521         show_version();
2522         exit(0);
2523         break;
2524       case 'X':
2525         /*
2526          *  Extension command line options have to be processed before
2527          *  we call epan_init() as they are supposed to be used by dissectors
2528          *  or taps very early in the registration process.
2529          */
2530         ex_opt_add(optarg);
2531         break;
2532       case '?':        /* Ignore errors - the "real" scan will catch them. */
2533         break;
2534     }
2535   }
2536
2537   /* Init the "Open file" dialog directory */
2538   /* (do this after the path settings are processed) */
2539   set_last_open_dir(get_persdatafile_dir());
2540
2541   /* Set getopt index back to initial value, so it will start with the
2542      first command line parameter again.  Also reset opterr to 1, so that
2543      error messages are printed by getopt().
2544
2545      XXX - this seems to work on most platforms, but time will tell.
2546      The Single UNIX Specification says "The getopt() function need
2547      not be reentrant", so this isn't guaranteed to work.  The Mac
2548      OS X 10.4[.x] getopt() man page says
2549
2550        In order to use getopt() to evaluate multiple sets of arguments, or to
2551        evaluate a single set of arguments multiple times, the variable optreset
2552        must be set to 1 before the second and each additional set of calls to
2553        getopt(), and the variable optind must be reinitialized.
2554
2555            ...
2556
2557        The optreset variable was added to make it possible to call the getopt()
2558        function multiple times.  This is an extension to the IEEE Std 1003.2
2559        (``POSIX.2'') specification.
2560
2561      which I think comes from one of the other BSDs.
2562
2563      XXX - if we want to control all the command-line option errors, so
2564      that we can display them where we choose (e.g., in a window), we'd
2565      want to leave opterr as 0, and produce our own messages using optopt.
2566      We'd have to check the value of optopt to see if it's a valid option
2567      letter, in which case *presumably* the error is "this option requires
2568      an argument but none was specified", or not a valid option letter,
2569      in which case *presumably* the error is "this option isn't valid".
2570      Some versions of getopt() let you supply a option string beginning
2571      with ':', which means that getopt() will return ':' rather than '?'
2572      for "this option requires an argument but none was specified", but
2573      not all do. */
2574   optind = optind_initial;
2575   opterr = 1;
2576
2577   /* Set the current locale according to the program environment.
2578    * We haven't localized anything, but some GTK widgets are localized
2579    * (the file selection dialogue, for example).
2580    * This also sets the C-language locale to the native environment. */
2581   gtk_set_locale();
2582
2583   /* Let GTK get its args (will need an X server, so do this after command line only commands handled) */
2584   gtk_init (&argc, &argv);
2585
2586   cf_callback_add(main_cf_callback, NULL);
2587
2588 #if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
2589   /* initialize our GTK eth_clist_type */
2590   init_eth_clist_type();
2591 #endif
2592
2593   /* Arrange that if we have no console window, and a GLib message logging
2594      routine is called to log a message, we pop up a console window.
2595
2596      We do that by inserting our own handler for all messages logged
2597      to the default domain; that handler pops up a console if necessary,
2598      and then calls the default handler. */
2599
2600   /* We might want to have component specific log levels later ... */
2601
2602   log_flags =
2603                     G_LOG_LEVEL_ERROR|
2604                     G_LOG_LEVEL_CRITICAL|
2605                     G_LOG_LEVEL_WARNING|
2606                     G_LOG_LEVEL_MESSAGE|
2607                     G_LOG_LEVEL_INFO|
2608                     G_LOG_LEVEL_DEBUG|
2609                     G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION;
2610
2611   g_log_set_handler(NULL,
2612                     log_flags,
2613                     console_log_handler, NULL /* user_data */);
2614   g_log_set_handler(LOG_DOMAIN_MAIN,
2615                     log_flags,
2616                     console_log_handler, NULL /* user_data */);
2617
2618 #ifdef HAVE_LIBPCAP
2619   g_log_set_handler(LOG_DOMAIN_CAPTURE,
2620                     log_flags,
2621                     console_log_handler, NULL /* user_data */);
2622   g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD,
2623                     log_flags,
2624                     console_log_handler, NULL /* user_data */);
2625
2626   /* Set the initial values in the capture_opts. This might be overwritten
2627      by preference settings and then again by the command line parameters. */
2628   capture_opts_init(capture_opts, &cfile);
2629
2630   capture_opts->snaplen             = MIN_PACKET_SIZE;
2631   capture_opts->has_ring_num_files  = TRUE;
2632 #endif
2633
2634   /* We won't come till here, if we had a "console only" command line parameter. */
2635   splash_win = splash_new("Loading Wireshark ...");
2636   if (init_progfile_dir_error != NULL) {
2637     simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
2638         "Can't get pathname of Wireshark: %s.\n"
2639         "It won't be possible to capture traffic.\n"
2640         "Report this to the Wireshark developers.",
2641         init_progfile_dir_error);
2642     g_free(init_progfile_dir_error);
2643   }
2644
2645   splash_update(RA_DISSECTORS, NULL, (gpointer)splash_win);
2646
2647   /* Register all dissectors; we must do this before checking for the
2648      "-G" flag, as the "-G" flag dumps information registered by the
2649      dissectors, and we must do it before we read the preferences, in
2650      case any dissectors register preferences. */
2651   epan_init(register_all_protocols,register_all_protocol_handoffs,
2652             splash_update, (gpointer) splash_win,
2653             failure_alert_box,open_failure_alert_box,read_failure_alert_box);
2654
2655   splash_update(RA_LISTENERS, NULL, (gpointer)splash_win);
2656
2657   /* Register all tap listeners; we do this before we parse the arguments,
2658      as the "-z" argument can specify a registered tap. */
2659
2660   /* we register the plugin taps before the other taps because
2661           stats_tree taps plugins will be registered as tap listeners
2662           by stats_tree_stat.c and need to registered before that */
2663
2664 #ifdef HAVE_PLUGINS
2665   register_all_plugin_tap_listeners();
2666 #endif
2667
2668   register_all_tap_listeners();
2669
2670   splash_update(RA_PREFERENCES, NULL, (gpointer)splash_win);
2671
2672   /* Now register the preferences for any non-dissector modules.
2673      We must do that before we read the preferences as well. */
2674   prefs_register_modules();
2675
2676   /* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
2677 #if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
2678   {
2679       GThread *ut;
2680       g_thread_init(NULL);
2681       gdk_threads_init();
2682       ut=g_thread_create(update_thread, NULL, FALSE, NULL);
2683       g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
2684   }
2685 #else  /* _WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
2686   /* this is to keep tap extensions updating once every 3 seconds */
2687   gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
2688 #endif /* !_WIN32 && GTK2 && G_THREADS_ENABLED */
2689
2690 #if HAVE_GNU_ADNS
2691   gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
2692 #endif
2693
2694   splash_update(RA_CONFIGURATION, NULL, (gpointer)splash_win);
2695
2696   prefs = read_configuration_files (&gdp_path, &dp_path);
2697
2698   /* Read the (static part) of the recent file. Only the static part of it will be read, */
2699   /* as we don't have the gui now to fill the recent lists which is done in the dynamic part. */
2700   /* We have to do this already here, so command line parameters can overwrite these values. */
2701   recent_read_static(&rf_path, &rf_open_errno);
2702
2703   init_cap_file(&cfile);
2704
2705   /* Now get our args */
2706   while ((opt = getopt(argc, argv, optstring)) != -1) {
2707     switch (opt) {
2708       /*** capture option specific ***/
2709       case 'a':        /* autostop criteria */
2710       case 'b':        /* Ringbuffer option */
2711       case 'c':        /* Capture xxx packets */
2712       case 'f':        /* capture filter */
2713       case 'k':        /* Start capture immediately */
2714       case 'H':        /* Hide capture info dialog box */
2715       case 'i':        /* Use interface xxx */
2716       case 'p':        /* Don't capture in promiscuous mode */
2717       case 'Q':        /* Quit after capture (just capture to file) */
2718       case 's':        /* Set the snapshot (capture) length */
2719       case 'S':        /* "Sync" mode: used for following file ala tail -f */
2720       case 'w':        /* Write to capture file xxx */
2721       case 'y':        /* Set the pcap data link type */
2722 #ifdef _WIN32
2723       case 'B':        /* Buffer size */
2724 #endif /* _WIN32 */
2725 #ifdef HAVE_LIBPCAP
2726         status = capture_opts_add_opt(capture_opts, opt, optarg, &start_capture);
2727         if(status != 0) {
2728             exit(status);
2729         }
2730 #else
2731         capture_option_specified = TRUE;
2732         arg_error = TRUE;
2733 #endif
2734         break;
2735
2736       /*** all non capture option specific ***/
2737       case 'C':
2738         /* Configuration profile settings were already processed just ignore them this time*/
2739         break;
2740       case 'D':        /* Print a list of capture devices and exit */
2741 #ifdef HAVE_LIBPCAP
2742         capture_opts_list_interfaces(FALSE);
2743         exit(0);
2744 #else
2745         capture_option_specified = TRUE;
2746         arg_error = TRUE;
2747 #endif
2748         break;
2749       case 'g':        /* Go to packet */
2750         go_to_packet = get_positive_int(optarg, "go to packet");
2751         break;
2752       case 'l':        /* Automatic scrolling in live capture mode */
2753 #ifdef HAVE_LIBPCAP
2754         auto_scroll_live = TRUE;
2755 #else
2756         capture_option_specified = TRUE;
2757         arg_error = TRUE;
2758 #endif
2759         break;
2760       case 'L':        /* Print list of link-layer types and exit */
2761 #ifdef HAVE_LIBPCAP
2762         list_link_layer_types = TRUE;
2763 #else
2764         capture_option_specified = TRUE;
2765         arg_error = TRUE;
2766 #endif
2767         break;
2768       case 'm':        /* Fixed-width font for the display */
2769         if (prefs->PREFS_GUI_FONT_NAME != NULL)
2770           g_free(prefs->PREFS_GUI_FONT_NAME);
2771         prefs->PREFS_GUI_FONT_NAME = g_strdup(optarg);
2772         break;
2773       case 'n':        /* No name resolution */
2774         g_resolv_flags = RESOLV_NONE;
2775         break;
2776       case 'N':        /* Select what types of addresses/port #s to resolve */
2777         if (g_resolv_flags == RESOLV_ALL)
2778           g_resolv_flags = RESOLV_NONE;
2779         badopt = string_to_name_resolve(optarg, &g_resolv_flags);
2780         if (badopt != '\0') {
2781           cmdarg_err("-N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'",
2782                         badopt);
2783           exit(1);
2784         }
2785         break;
2786       case 'o':        /* Override preference from command line */
2787         switch (prefs_set_pref(optarg)) {
2788         case PREFS_SET_OK:
2789           break;
2790         case PREFS_SET_SYNTAX_ERR:
2791           cmdarg_err("Invalid -o flag \"%s\"", optarg);
2792           exit(1);
2793           break;
2794         case PREFS_SET_NO_SUCH_PREF:
2795           /* not a preference, might be a recent setting */
2796           switch (recent_set_arg(optarg)) {
2797             case PREFS_SET_OK:
2798               break;
2799             case PREFS_SET_SYNTAX_ERR:
2800               /* shouldn't happen, checked already above */
2801               cmdarg_err("Invalid -o flag \"%s\"", optarg);
2802               exit(1);
2803               break;
2804             case PREFS_SET_NO_SUCH_PREF:
2805             case PREFS_SET_OBSOLETE:
2806               cmdarg_err("-o flag \"%s\" specifies unknown preference/recent value",
2807                     optarg);
2808               exit(1);
2809               break;
2810             default:
2811               g_assert_not_reached();
2812             }
2813           break;
2814         case PREFS_SET_OBSOLETE:
2815           cmdarg_err("-o flag \"%s\" specifies obsolete preference",
2816                         optarg);
2817           exit(1);
2818           break;
2819         default:
2820           g_assert_not_reached();
2821         }
2822         break;
2823       case 'P':
2824         /* Path settings were already processed just ignore them this time*/
2825         break;
2826       case 'r':        /* Read capture file xxx */
2827         /* We may set "last_open_dir" to "cf_name", and if we change
2828            "last_open_dir" later, we free the old value, so we have to
2829            set "cf_name" to something that's been allocated. */
2830 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2831         /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2832         cf_name = g_locale_to_utf8(optarg, -1, NULL, NULL, NULL);
2833 #else
2834         cf_name = g_strdup(optarg);
2835 #endif
2836         break;
2837       case 'R':        /* Read file filter */
2838         rfilter = optarg;
2839         break;
2840       case 't':        /* Time stamp type */
2841         if (strcmp(optarg, "r") == 0)
2842           timestamp_set_type(TS_RELATIVE);
2843         else if (strcmp(optarg, "a") == 0)
2844           timestamp_set_type(TS_ABSOLUTE);
2845         else if (strcmp(optarg, "ad") == 0)
2846           timestamp_set_type(TS_ABSOLUTE_WITH_DATE);
2847         else if (strcmp(optarg, "d") == 0)
2848           timestamp_set_type(TS_DELTA);
2849         else if (strcmp(optarg, "dd") == 0)
2850           timestamp_set_type(TS_DELTA_DIS);
2851         else if (strcmp(optarg, "e") == 0)
2852           timestamp_set_type(TS_EPOCH);
2853         else {
2854           cmdarg_err("Invalid time stamp type \"%s\"", optarg);
2855           cmdarg_err_cont("It must be \"r\" for relative, \"a\" for absolute,");
2856           cmdarg_err_cont("\"ad\" for absolute with date, or \"d\" for delta.");
2857           exit(1);
2858         }
2859         break;
2860       case 'X':
2861           /* ext ops were already processed just ignore them this time*/
2862           break;
2863       case 'z':
2864         /* We won't call the init function for the stat this soon
2865            as it would disallow MATE's fields (which are registered
2866            by the preferences set callback) from being used as
2867            part of a tap filter.  Instead, we just add the argument
2868            to a list of stat arguments. */
2869         if (!process_stat_cmd_arg(optarg)) {
2870           cmdarg_err("Invalid -z argument.");
2871           cmdarg_err_cont("  -z argument must be one of :");
2872           list_stat_cmd_args();
2873           exit(1);
2874         }
2875         break;
2876       default:
2877       case '?':        /* Bad flag - print usage message */
2878         arg_error = TRUE;
2879         break;
2880     }
2881   }
2882   argc -= optind;
2883   argv += optind;
2884   if (argc >= 1) {
2885     if (cf_name != NULL) {
2886       /*
2887        * Input file name specified with "-r" *and* specified as a regular
2888        * command-line argument.
2889        */
2890       cmdarg_err("File name specified both with -r and regular argument");
2891       arg_error = TRUE;
2892     } else {
2893       /*
2894        * Input file name not specified with "-r", and a command-line argument
2895        * was specified; treat it as the input file name.
2896        *
2897        * Yes, this is different from tshark, where non-flag command-line
2898        * arguments are a filter, but this works better on GUI desktops
2899        * where a command can be specified to be run to open a particular
2900        * file - yes, you could have "-r" as the last part of the command,
2901        * but that's a bit ugly.
2902        */
2903 #if defined _WIN32 && (GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 6))
2904       /* since GLib 2.6, we need to convert filenames to utf8 for Win32 */
2905       cf_name = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
2906 #else
2907       cf_name = g_strdup(argv[0]);
2908 #endif
2909     }
2910     argc--;
2911     argv++;
2912   }
2913
2914
2915
2916   if (argc != 0) {
2917     /*
2918      * Extra command line arguments were specified; complain.
2919      */
2920     cmdarg_err("Invalid argument: %s", argv[0]);
2921     arg_error = TRUE;
2922   }
2923
2924   if (arg_error) {
2925 #ifndef HAVE_LIBPCAP
2926     if (capture_option_specified) {
2927       cmdarg_err("This version of Wireshark was not built with support for capturing packets.");
2928     }
2929 #endif
2930     print_usage(FALSE);
2931     exit(1);
2932   }
2933
2934 #ifdef HAVE_LIBPCAP
2935   if (start_capture && list_link_layer_types) {
2936     /* Specifying *both* is bogus. */
2937     cmdarg_err("You can't specify both -L and a live capture.");
2938     exit(1);
2939   }
2940
2941   if (list_link_layer_types) {
2942     /* We're supposed to list the link-layer types for an interface;
2943        did the user also specify a capture file to be read? */
2944     if (cf_name) {
2945       /* Yes - that's bogus. */
2946       cmdarg_err("You can't specify -L and a capture file to be read.");
2947       exit(1);
2948     }
2949     /* No - did they specify a ring buffer option? */
2950     if (capture_opts->multi_files_on) {
2951       cmdarg_err("Ring buffer requested, but a capture isn't being done.");
2952       exit(1);
2953     }
2954   } else {
2955     /* We're supposed to do a live capture; did the user also specify
2956        a capture file to be read? */
2957     if (start_capture && cf_name) {
2958       /* Yes - that's bogus. */
2959       cmdarg_err("You can't specify both a live capture and a capture file to be read.");
2960       exit(1);
2961     }
2962
2963     /* No - was the ring buffer option specified and, if so, does it make
2964        sense? */
2965     if (capture_opts->multi_files_on) {
2966       /* Ring buffer works only under certain conditions:
2967          a) ring buffer does not work with temporary files;
2968          b) real_time_mode and multi_files_on are mutually exclusive -
2969             real_time_mode takes precedence;
2970          c) it makes no sense to enable the ring buffer if the maximum
2971             file size is set to "infinite". */
2972       if (capture_opts->save_file == NULL) {
2973         cmdarg_err("Ring buffer requested, but capture isn't being saved to a permanent file.");
2974         capture_opts->multi_files_on = FALSE;
2975       }
2976 /*      if (capture_opts->real_time_mode) {
2977         cmdarg_err("Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.");
2978         capture_opts->multi_files_on = FALSE;
2979       }*/
2980       if (!capture_opts->has_autostop_filesize && !capture_opts->has_file_duration) {
2981         cmdarg_err("Ring buffer requested, but no maximum capture file size or duration were specified.");
2982 /* XXX - this must be redesigned as the conditions changed */
2983 /*      capture_opts->multi_files_on = FALSE;*/
2984       }
2985     }
2986   }
2987
2988   if (start_capture || list_link_layer_types) {
2989     /* Did the user specify an interface to use? */
2990     if (!capture_opts_trim_iface(capture_opts,
2991         (prefs->capture_device) ? get_if_name(prefs->capture_device) : NULL)) {
2992         exit(2);
2993     }
2994   }
2995
2996   if (list_link_layer_types) {
2997     status = capture_opts_list_link_layer_types(capture_opts, FALSE);
2998     exit(status);
2999   }
3000
3001   /* Fill in capture options with values from the preferences */
3002   prefs_to_capture_opts();
3003
3004   capture_opts_trim_snaplen(capture_opts, MIN_PACKET_SIZE);
3005   capture_opts_trim_ring_num_files(capture_opts);
3006 #endif /* HAVE_LIBPCAP */
3007
3008   /* Notify all registered modules that have had any of their preferences
3009      changed either from one of the preferences file or from the command
3010      line that their preferences have changed. */
3011   prefs_apply_all();
3012
3013   /* disabled protocols as per configuration file */
3014   if (gdp_path == NULL && dp_path == NULL) {
3015     set_disabled_protos_list();
3016   }
3017
3018   build_column_format_array(&cfile, TRUE);
3019
3020   /* read in rc file from global and personal configuration paths. */
3021   rc_file = get_datafile_path(RC_FILE);
3022   gtk_rc_parse(rc_file);
3023   rc_file = get_persconffile_path(RC_FILE, FALSE, FALSE);
3024   gtk_rc_parse(rc_file);
3025
3026   font_init();
3027
3028   /* close the splash screen, as we are going to open the main window now */
3029   splash_destroy(splash_win);
3030
3031   /************************************************************************/
3032   /* Everything is prepared now, preferences and command line was read in */
3033
3034   /* Pop up the main window. */
3035   create_main_window(pl_size, tv_size, bv_size, prefs);
3036
3037   /* Read the dynamic part of the recent file, as we have the gui now ready for it. */
3038   recent_read_dynamic(&rf_path, &rf_open_errno);
3039   color_filters_enable(recent.packet_list_colorize);
3040
3041   /* rearrange all the widgets as we now have all recent settings ready for this */
3042   main_widgets_rearrange();
3043
3044   /* Fill in column titles.  This must be done after the top level window
3045      is displayed.
3046
3047      XXX - is that still true, with fixed-width columns? */
3048   packet_list_set_column_titles();
3049
3050   menu_recent_read_finished();
3051   menu_auto_scroll_live_changed(auto_scroll_live);
3052
3053
3054   switch (user_font_apply()) {
3055   case FA_SUCCESS:
3056       break;
3057   case FA_FONT_NOT_RESIZEABLE:
3058       /* "user_font_apply()" popped up an alert box. */
3059       /* turn off zooming - font can't be resized */
3060   case FA_FONT_NOT_AVAILABLE:
3061       /* XXX - did we successfully load the un-zoomed version earlier?
3062       If so, this *probably* means the font is available, but not at
3063       this particular zoom level, but perhaps some other failure
3064       occurred; I'm not sure you can determine which is the case,
3065       however. */
3066       /* turn off zooming - zoom level is unavailable */
3067   default:
3068       /* in any other case than FA_SUCCESS, turn off zooming */
3069       recent.gui_zoom_level = 0;
3070       /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
3071   }
3072
3073   dnd_init(top_level);
3074
3075   colors_init();
3076   color_filters_init();
3077   decode_as_init();
3078
3079   /* the window can be sized only, if it's not already shown, so do it now! */
3080   main_load_window_geometry(top_level);
3081
3082   /* Tell the user not to run as root. */
3083   if (running_with_special_privs() && recent.privs_warn_if_elevated) {
3084     cur_user = get_cur_username();
3085     cur_group = get_cur_groupname();
3086     priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3087       "Running as user \"%s\" and group \"%s\".\n"
3088       "This could be dangerous.", cur_user, cur_group);
3089     g_free(cur_user);
3090     g_free(cur_group);
3091     simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
3092     simple_dialog_set_cb(priv_warning_dialog, priv_warning_dialog_cb, NULL);
3093   }
3094
3095 #ifdef _WIN32
3096   /* Warn the user if npf.sys isn't loaded. */
3097   if (!npf_sys_is_running() && recent.privs_warn_if_no_npf && get_os_major_version() >= 6) {
3098     priv_warning_dialog = simple_dialog(ESD_TYPE_WARN, ESD_BTN_OK,
3099       "The NPF driver isn't running.  You may have trouble\n"
3100       "capturing or listing interfaces.");
3101     simple_dialog_check_set(priv_warning_dialog, "Don't show this message again.");
3102     simple_dialog_set_cb(priv_warning_dialog, npf_warning_dialog_cb, NULL);
3103   }
3104 #endif
3105
3106   /* If we were given the name of a capture file, read it in now;
3107      we defer it until now, so that, if we can't open it, and pop
3108      up an alert box, the alert box is more likely to come up on
3109      top of the main window - but before the preference-file-error
3110      alert box, so, if we get one of those, it's more likely to come
3111      up on top of us. */
3112   if (cf_name) {
3113     show_main_window(TRUE);
3114     if (rfilter != NULL) {
3115       if (!dfilter_compile(rfilter, &rfcode)) {
3116         bad_dfilter_alert_box(rfilter);
3117         rfilter_parse_failed = TRUE;
3118       }
3119     }
3120     if (!rfilter_parse_failed) {
3121       if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
3122         /* "cf_open()" succeeded, so it closed the previous
3123            capture file, and thus destroyed any previous read filter
3124            attached to "cf". */
3125
3126         cfile.rfcode = rfcode;
3127         /* Open stat windows; we do so after creating the main window,
3128            to avoid GTK warnings, and after successfully opening the
3129            capture file, so we know we have something to compute stats
3130            on, and after registering all dissectors, so that MATE will
3131            have registered its field array and we can have a tap filter
3132            with one of MATE's late-registered fields as part of the
3133            filter. */
3134         start_requested_stats();
3135
3136         /* Read the capture file. */
3137         switch (cf_read(&cfile)) {
3138
3139         case CF_READ_OK:
3140         case CF_READ_ERROR:
3141           /* Just because we got an error, that doesn't mean we were unable
3142              to read any of the file; we handle what we could get from the
3143              file. */
3144           /* if the user told us to jump to a specific packet, do it now */
3145           if(go_to_packet != 0) {
3146             cf_goto_frame(&cfile, go_to_packet);
3147           }
3148           break;
3149
3150         case CF_READ_ABORTED:
3151           /* Exit now. */
3152           gtk_exit(0);
3153           break;
3154         }
3155         /* Save the name of the containing directory specified in the
3156            path name, if any; we can write over cf_name, which is a
3157            good thing, given that "get_dirname()" does write over its
3158            argument. */
3159         s = get_dirname(cf_name);
3160         set_last_open_dir(s);
3161         g_free(cf_name);
3162         cf_name = NULL;
3163       } else {
3164         if (rfcode != NULL)
3165           dfilter_free(rfcode);
3166         cfile.rfcode = NULL;
3167         show_main_window(FALSE);
3168         set_menus_for_capture_in_progress(FALSE);
3169       }
3170     }
3171   } else {
3172 #ifdef HAVE_LIBPCAP
3173     if (start_capture) {
3174       if (capture_opts->save_file != NULL) {
3175         /* Save the directory name for future file dialogs. */
3176         /* (get_dirname overwrites filename) */
3177         s = get_dirname(g_strdup(capture_opts->save_file));
3178         set_last_open_dir(s);
3179         g_free(s);
3180       }
3181       /* "-k" was specified; start a capture. */
3182       show_main_window(TRUE);
3183       if (capture_start(capture_opts)) {
3184         /* The capture started.  Open stat windows; we do so after creating
3185            the main window, to avoid GTK warnings, and after successfully
3186            opening the capture file, so we know we have something to compute
3187            stats on, and after registering all dissectors, so that MATE will
3188            have registered its field array and we can have a tap filter with
3189            one of MATE's late-registered fields as part of the filter. */
3190         start_requested_stats();
3191       }
3192     }
3193     else {
3194       show_main_window(FALSE);
3195       set_menus_for_capture_in_progress(FALSE);
3196     }
3197
3198     /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
3199     if (!start_capture && strlen(capture_opts->cfilter) == 0) {
3200       g_free(capture_opts->cfilter);
3201       capture_opts->cfilter = g_strdup(get_conn_cfilter());
3202     }
3203 #else /* HAVE_LIBPCAP */
3204     show_main_window(FALSE);
3205     set_menus_for_capture_in_progress(FALSE);
3206 #endif /* HAVE_LIBPCAP */
3207   }
3208
3209   /* register our pid if we are being run from a U3 device */
3210   u3_register_pid();
3211
3212   g_log(LOG_DOMAIN_MAIN, G_LOG_LEVEL_INFO, "Wireshark is up and ready to go");
3213
3214   /* we'll enter the GTK loop now and hand the control over to GTK ... */
3215   gtk_main();
3216   /* ... back from GTK, we're going down now! */
3217
3218   /* deregister our pid */
3219   u3_deregister_pid();
3220
3221   epan_cleanup();
3222   g_free(rc_file);
3223
3224 #ifdef  HAVE_AIRPDCAP
3225         /*      Davide Schiera (2006-11-18): destroy AirPDcap context                                                   */
3226         AirPDcapDestroyContext(&airpdcap_ctx);
3227         /* Davide Schiera (2006-11-18) -------------------------------------------      */
3228 #endif
3229
3230 #ifdef _WIN32
3231   /* hide the (unresponsive) main window, while asking the user to close the console window */
3232   gtk_widget_hide(top_level);
3233
3234   /* Shutdown windows sockets */
3235   WSACleanup();
3236
3237   /* For some unknown reason, the "atexit()" call in "create_console()"
3238      doesn't arrange that "destroy_console()" be called when we exit,
3239      so we call it here if a console was created. */
3240   destroy_console();
3241 #endif
3242
3243   gtk_exit(0);
3244
3245   /* This isn't reached, but we need it to keep GCC from complaining
3246      that "main()" returns without returning a value - it knows that
3247      "exit()" never returns, but it doesn't know that "gtk_exit()"
3248      doesn't, as GTK+ doesn't declare it with the attribute
3249      "noreturn". */
3250   return 0;     /* not reached */
3251 }
3252
3253 #ifdef _WIN32
3254
3255 /* We build this as a GUI subsystem application on Win32, so
3256    "WinMain()", not "main()", gets called.
3257
3258    Hack shamelessly stolen from the Win32 port of the GIMP. */
3259 #ifdef __GNUC__
3260 #define _stdcall  __attribute__((stdcall))
3261 #endif
3262
3263 int _stdcall
3264 WinMain (struct HINSTANCE__ *hInstance,
3265          struct HINSTANCE__ *hPrevInstance,
3266          char               *lpszCmdLine,
3267          int                 nCmdShow)
3268 {
3269 #if GTK_MAJOR_VERSION >= 2
3270   INITCOMMONCONTROLSEX comm_ctrl;
3271
3272   /* Initialize our controls. Required for native Windows file dialogs. */
3273   memset (&comm_ctrl, 0, sizeof(comm_ctrl));
3274   comm_ctrl.dwSize = sizeof(comm_ctrl);
3275   /* Includes the animate, header, hot key, list view, progress bar,
3276    * status bar, tab, tooltip, toolbar, trackbar, tree view, and
3277    * up-down controls
3278    */
3279   comm_ctrl.dwICC = ICC_WIN95_CLASSES;
3280   InitCommonControlsEx(&comm_ctrl);
3281
3282   /* RichEd20.DLL is needed for filter entries. */
3283   LoadLibrary(_T("riched20.dll"));
3284 #endif /* GTK_MAJOR_VERSION >= 2 */
3285
3286   has_console = FALSE;
3287   return main (__argc, __argv);
3288 }
3289
3290 /*
3291  * If this application has no console window to which its standard output
3292  * would go, create one.
3293  */
3294 void
3295 create_console(void)
3296 {
3297   if (!has_console) {
3298     /* We have no console to which to print the version string, so
3299        create one and make it the standard input, output, and error. */
3300     if (!AllocConsole())
3301       return;   /* couldn't create console */
3302     eth_freopen("CONIN$", "r", stdin);
3303     eth_freopen("CONOUT$", "w", stdout);
3304     eth_freopen("CONOUT$", "w", stderr);
3305
3306     /* Well, we have a console now. */
3307     has_console = TRUE;
3308
3309     /* Now register "destroy_console()" as a routine to be called just
3310        before the application exits, so that we can destroy the console
3311        after the user has typed a key (so that the console doesn't just
3312        disappear out from under them, giving the user no chance to see
3313        the message(s) we put in there). */
3314     atexit(destroy_console);
3315
3316     SetConsoleTitle(_T("Wireshark Debug Console"));
3317   }
3318 }
3319
3320 static void
3321 destroy_console(void)
3322 {
3323   if (has_console) {
3324     printf("\n\nPress any key to exit\n");
3325     _getch();
3326     FreeConsole();
3327   }
3328 }
3329 #endif /* _WIN32 */
3330
3331
3332 /* This routine should not be necessary, at least as I read the GLib
3333    source code, as it looks as if GLib is, on Win32, *supposed* to
3334    create a console window into which to display its output.
3335
3336    That doesn't happen, however.  I suspect there's something completely
3337    broken about that code in GLib-for-Win32, and that it may be related
3338    to the breakage that forces us to just call "printf()" on the message
3339    rather than passing the message on to "g_log_default_handler()"
3340    (which is the routine that does the aforementioned non-functional
3341    console window creation). */
3342 static void
3343 console_log_handler(const char *log_domain, GLogLevelFlags log_level,
3344                     const char *message, gpointer user_data _U_)
3345 {
3346   time_t curr;
3347   struct tm *today;
3348   const char *level;
3349
3350
3351   /* ignore log message, if log_level isn't interesting.
3352      If preferences aren't loaded yet, display message anyway */
3353   if((log_level & G_LOG_LEVEL_MASK & prefs.console_log_level) == 0 &&
3354      prefs.console_log_level != 0) {
3355     return;
3356   }
3357
3358   /* create a "timestamp" */
3359   time(&curr);
3360   today = localtime(&curr);
3361
3362 #ifdef _WIN32
3363   if (prefs.gui_console_open != console_open_never || log_level & G_LOG_LEVEL_ERROR) {
3364     /* the user wants a console or the application will terminate immediately */
3365     create_console();
3366   }
3367   if (has_console) {
3368     /* For some unknown reason, the above doesn't appear to actually cause
3369        anything to be sent to the standard output, so we'll just splat the
3370        message out directly, just to make sure it gets out. */
3371 #endif
3372     switch(log_level & G_LOG_LEVEL_MASK) {
3373     case G_LOG_LEVEL_ERROR:
3374         level = "Err ";
3375         break;
3376     case G_LOG_LEVEL_CRITICAL:
3377         level = "Crit";
3378         break;
3379     case G_LOG_LEVEL_WARNING:
3380         level = "Warn";
3381         break;
3382     case G_LOG_LEVEL_MESSAGE:
3383         level = "Msg ";
3384         break;
3385     case G_LOG_LEVEL_INFO:
3386         level = "Info";
3387         break;
3388     case G_LOG_LEVEL_DEBUG:
3389         level = "Dbg ";
3390         break;
3391     default:
3392         fprintf(stderr, "unknown log_level %u\n", log_level);
3393         level = NULL;
3394         g_assert_not_reached();
3395     }
3396
3397     fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n",
3398             today->tm_hour, today->tm_min, today->tm_sec,
3399             log_domain != NULL ? log_domain : "",
3400             level, message);
3401 #ifdef _WIN32
3402     if(log_level & G_LOG_LEVEL_ERROR) {
3403         /* wait for a key press before the following error handler will terminate the program
3404            this way the user at least can read the error message */
3405         printf("\n\nPress any key to exit\n");
3406         _getch();
3407     }
3408   } else {
3409     g_log_default_handler(log_domain, log_level, message, user_data);
3410   }
3411 #endif
3412 }
3413
3414
3415 static GtkWidget *info_bar_new(void)
3416 {
3417     int i;
3418
3419     /* tip: tooltips don't work on statusbars! */
3420     info_bar = gtk_statusbar_new();
3421     main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
3422     file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
3423     help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
3424     filter_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "filter");
3425 #if GTK_MAJOR_VERSION >= 2
3426     gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(info_bar), FALSE);
3427 #endif
3428     gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
3429
3430     for (i = 0; i < NUM_STATUS_LEVELS; i++) {
3431         status_levels[i] = 0;
3432     }
3433
3434     return info_bar;
3435 }
3436
3437 static GtkWidget *packets_bar_new(void)
3438 {
3439     /* tip: tooltips don't work on statusbars! */
3440     packets_bar = gtk_statusbar_new();
3441     packets_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(packets_bar), "packets");
3442     packets_bar_update();
3443 #if GTK_MAJOR_VERSION >= 2
3444     gtk_statusbar_set_has_resize_grip(GTK_STATUSBAR(packets_bar), FALSE);
3445 #endif
3446
3447     return packets_bar;
3448 }
3449
3450 static GtkWidget *profile_bar_new(void)
3451 {
3452     /* tip: tooltips don't work on statusbars! */
3453     profile_bar = gtk_statusbar_new();
3454     profile_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(profile_bar), "profile");
3455     profile_bar_update();
3456
3457     return profile_bar;
3458 }
3459
3460
3461 /*
3462  * Helper for main_widgets_rearrange()
3463  */
3464 static void foreach_remove_a_child(GtkWidget *widget, gpointer data) {
3465     gtk_container_remove(GTK_CONTAINER(data), widget);
3466 }
3467
3468 static GtkWidget *main_widget_layout(gint layout_content)
3469 {
3470     switch(layout_content) {
3471     case(layout_pane_content_none):
3472         return NULL;
3473     case(layout_pane_content_plist):
3474         return pkt_scrollw;
3475     case(layout_pane_content_pdetails):
3476         return tv_scrollw;
3477     case(layout_pane_content_pbytes):
3478         return byte_nb_ptr;
3479     default:
3480         g_assert_not_reached();
3481         return NULL;
3482     }
3483 }
3484
3485
3486 /*
3487  * Rearrange the main window widgets
3488  */
3489 void main_widgets_rearrange(void) {
3490     GtkWidget *first_pane_widget1, *first_pane_widget2;
3491     GtkWidget *second_pane_widget1, *second_pane_widget2;
3492     gboolean split_top_left;
3493
3494     /* be a bit faster */
3495     gtk_widget_hide(main_vbox);
3496
3497     /* be sure, we don't loose a widget while rearranging */
3498     gtk_widget_ref(menubar);
3499     gtk_widget_ref(main_tb);
3500     gtk_widget_ref(filter_tb);
3501
3502 #ifdef HAVE_AIRPCAP
3503     gtk_widget_ref(airpcap_tb);
3504 #endif
3505
3506     gtk_widget_ref(pkt_scrollw);
3507     gtk_widget_ref(tv_scrollw);
3508     gtk_widget_ref(byte_nb_ptr);
3509     gtk_widget_ref(stat_hbox);
3510     gtk_widget_ref(info_bar);
3511     gtk_widget_ref(packets_bar);
3512     gtk_widget_ref(profile_bar);
3513     gtk_widget_ref(status_pane_left);
3514     gtk_widget_ref(status_pane_right);
3515     gtk_widget_ref(main_pane_v1);
3516     gtk_widget_ref(main_pane_v2);
3517     gtk_widget_ref(main_pane_h1);
3518     gtk_widget_ref(main_pane_h2);
3519     gtk_widget_ref(welcome_pane);
3520
3521     /* empty all containers participating */
3522     gtk_container_foreach(GTK_CONTAINER(main_vbox),     foreach_remove_a_child, main_vbox);
3523     gtk_container_foreach(GTK_CONTAINER(stat_hbox),     foreach_remove_a_child, stat_hbox);
3524     gtk_container_foreach(GTK_CONTAINER(status_pane_left),   foreach_remove_a_child, status_pane_left);
3525     gtk_container_foreach(GTK_CONTAINER(status_pane_right),   foreach_remove_a_child, status_pane_right);
3526     gtk_container_foreach(GTK_CONTAINER(main_pane_v1),  foreach_remove_a_child, main_pane_v1);
3527     gtk_container_foreach(GTK_CONTAINER(main_pane_v2),  foreach_remove_a_child, main_pane_v2);
3528     gtk_container_foreach(GTK_CONTAINER(main_pane_h1),  foreach_remove_a_child, main_pane_h1);
3529     gtk_container_foreach(GTK_CONTAINER(main_pane_h2),  foreach_remove_a_child, main_pane_h2);
3530
3531     /* add the menubar always at the top */
3532     gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
3533
3534     /* main toolbar */
3535     gtk_box_pack_start(GTK_BOX(main_vbox), main_tb, FALSE, TRUE, 0);
3536
3537     /* filter toolbar in toolbar area */
3538     if (!prefs.filter_toolbar_show_in_statusbar) {
3539         gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
3540     }
3541
3542 #ifdef HAVE_AIRPCAP
3543     /* airpcap toolbar */
3544     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3545 #endif
3546
3547     /* fill the main layout panes */
3548     switch(prefs.gui_layout_type) {
3549     case(layout_type_5):
3550         main_first_pane  = main_pane_v1;
3551         main_second_pane = main_pane_v2;
3552         split_top_left = FALSE;
3553         break;
3554     case(layout_type_2):
3555         main_first_pane  = main_pane_v1;
3556         main_second_pane = main_pane_h1;
3557         split_top_left = FALSE;
3558         break;
3559     case(layout_type_1):
3560         main_first_pane  = main_pane_v1;
3561         main_second_pane = main_pane_h1;
3562         split_top_left = TRUE;
3563         break;
3564     case(layout_type_4):
3565         main_first_pane  = main_pane_h1;
3566         main_second_pane = main_pane_v1;
3567         split_top_left = FALSE;
3568         break;
3569     case(layout_type_3):
3570         main_first_pane  = main_pane_h1;
3571         main_second_pane = main_pane_v1;
3572         split_top_left = TRUE;
3573         break;
3574     case(layout_type_6):
3575         main_first_pane  = main_pane_h1;
3576         main_second_pane = main_pane_h2;
3577         split_top_left = FALSE;
3578         break;
3579     default:
3580         main_first_pane = NULL;
3581         main_second_pane = NULL;
3582         split_top_left = FALSE;
3583         g_assert_not_reached();
3584     }
3585     if (split_top_left) {
3586         first_pane_widget1 = main_second_pane;
3587         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3588         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
3589         first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3590     } else {
3591         first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
3592         first_pane_widget2 = main_second_pane;
3593         second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
3594         second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
3595     }
3596     if (first_pane_widget1 != NULL)
3597         gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
3598     if (first_pane_widget2 != NULL)
3599         gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
3600     if (second_pane_widget1 != NULL)
3601         gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
3602     if (second_pane_widget2 != NULL)
3603         gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
3604
3605     gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
3606
3607     /* welcome pane */
3608     gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
3609
3610     /* statusbar hbox */
3611     gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
3612
3613     /* filter toolbar in statusbar hbox */
3614     if (prefs.filter_toolbar_show_in_statusbar) {
3615         gtk_box_pack_start(GTK_BOX(stat_hbox), filter_tb, FALSE, TRUE, 1);
3616     }
3617
3618 #ifdef HAVE_AIRPCAP
3619     /* airpcap toolbar */
3620     gtk_box_pack_start(GTK_BOX(main_vbox), airpcap_tb, FALSE, TRUE, 1);
3621 #endif
3622
3623     /* statusbar */
3624     gtk_box_pack_start(GTK_BOX(stat_hbox), status_pane_left, TRUE, TRUE, 0);
3625     gtk_paned_pack1(GTK_PANED(status_pane_left), info_bar, FALSE, FALSE);
3626     gtk_paned_pack2(GTK_PANED(status_pane_left), status_pane_right, TRUE, FALSE);
3627     gtk_paned_pack1(GTK_PANED(status_pane_right), packets_bar, TRUE, FALSE);
3628     gtk_paned_pack2(GTK_PANED(status_pane_right), profile_bar, FALSE, FALSE);
3629
3630     /* hide widgets on users recent settings */
3631     main_widgets_show_or_hide();
3632
3633     gtk_widget_show(main_vbox);
3634 }
3635
3636 static void
3637 is_widget_visible(GtkWidget *widget, gpointer data)
3638 {
3639     gboolean *is_visible = data;
3640
3641     if (!*is_visible) {
3642         if (GTK_WIDGET_VISIBLE(widget))
3643             *is_visible = TRUE;
3644     }
3645 }
3646
3647 /*#define SHOW_WELCOME_PAGE*/
3648 #ifdef SHOW_WELCOME_PAGE
3649 /* XXX - There seems to be some disagreement about if and how this feature should be implemented.
3650    As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
3651 GtkWidget *
3652 welcome_item(const gchar *stock_item, const gchar * label, const gchar * message, const gchar * tooltip,
3653                          GtkSignalFunc callback, void *callback_data)
3654 {
3655     GtkWidget *w, *item_hb;
3656 #if GTK_MAJOR_VERSION >= 2
3657     gchar *formatted_message;
3658     GtkTooltips *tooltips;
3659
3660     tooltips = gtk_tooltips_new();
3661 #endif
3662
3663     item_hb = gtk_hbox_new(FALSE, 1);
3664
3665     w = BUTTON_NEW_FROM_STOCK(stock_item);
3666     WIDGET_SET_SIZE(w, 80, 40);
3667 #if GTK_MAJOR_VERSION >= 2
3668     gtk_button_set_label(GTK_BUTTON(w), label);
3669     gtk_tooltips_set_tip(tooltips, w, tooltip, NULL);
3670 #endif
3671     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
3672     SIGNAL_CONNECT(w, "clicked", callback, callback_data);
3673
3674     w = gtk_label_new(message);
3675     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3676 #if GTK_MAJOR_VERSION >= 2
3677     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
3678     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
3679     g_free(formatted_message);
3680 #endif
3681
3682     gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
3683
3684     return item_hb;
3685 }
3686
3687
3688 GtkWidget *
3689 welcome_header_new(void)
3690 {
3691     GtkWidget *item_vb;
3692     GtkWidget *item_hb;
3693     GtkWidget *eb;
3694     GdkColor bg;
3695     GtkWidget *icon;
3696     gchar *message;
3697     GtkWidget *w;
3698
3699
3700     /* background color of the header bar */
3701     bg.pixel = 0;
3702     bg.red = 154 * 255;
3703     bg.green = 210 * 255;
3704     bg.blue = 229 * 255;
3705
3706     item_vb = gtk_vbox_new(FALSE, 0);
3707
3708     /* colorize vbox */
3709     get_color(&bg);
3710     eb = gtk_event_box_new();
3711     gtk_container_add(GTK_CONTAINER(eb), item_vb);
3712 #if GTK_MAJOR_VERSION >= 2
3713     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &bg);
3714 #endif
3715
3716     item_hb = gtk_hbox_new(FALSE, 0);
3717     gtk_box_pack_start(GTK_BOX(item_vb), item_hb, FALSE, FALSE, 10);
3718
3719     icon = xpm_to_widget_from_parent(top_level, wssplash_xpm);
3720     /*icon = xpm_to_widget_from_parent(top_level, wsicon64_xpm);*/
3721     gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 10);
3722
3723 #if GTK_MAJOR_VERSION < 2
3724     message = "The World's Most Popular Network Protocol Analyzer";
3725 #else
3726     message = "<span weight=\"bold\" size=\"x-large\">" "The World's Most Popular Network Protocol Analyzer" "</span>";
3727 #endif
3728     w = gtk_label_new(message);
3729 #if GTK_MAJOR_VERSION >= 2
3730     gtk_label_set_markup(GTK_LABEL(w), message);
3731 #endif
3732     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
3733     gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
3734
3735     gtk_widget_show_all(eb);
3736
3737     return eb;
3738 }
3739
3740 GtkWidget *
3741 welcome_topic_header_new(const char *header)
3742 {
3743     GtkWidget *w;
3744     GdkColor bg;
3745     GtkWidget *eb;
3746 #if GTK_MAJOR_VERSION >= 2
3747     gchar *formatted_message;
3748 #endif
3749
3750
3751     w = gtk_label_new(header);
3752 #if GTK_MAJOR_VERSION >= 2
3753     formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", header);
3754     gtk_label_set_markup(GTK_LABEL(w), formatted_message);
3755     g_free(formatted_message);
3756 #endif
3757
3758     /* topic header background color */
3759     bg.pixel = 0;
3760     bg.red = 24 * 255;
3761     bg.green = 151 * 255;
3762     bg.blue = 192 * 255;
3763
3764     /* colorize vbox */
3765     get_color(&bg);
3766     eb = gtk_event_box_new();
3767     gtk_container_add(GTK_CONTAINER(eb), w);
3768 #if GTK_MAJOR_VERSION >= 2
3769     gtk_widget_modify_bg(eb, GTK_STATE_NORMAL, &bg);
3770 #endif
3771
3772     return eb;
3773 }
3774
3775
3776 GtkWidget *
3777 welcome_topic_new(const char *header, GtkWidget **to_fill)
3778 {
3779     GtkWidget *topic_vb;
3780     GtkWidget *layout_vb;
3781     GtkWidget *topic_eb;
3782     GtkWidget *topic_header;
3783     GdkColor bg;
3784
3785     topic_vb = gtk_vbox_new(FALSE, 0);
3786
3787         /* topic content background color */
3788     bg.pixel = 0;
3789     bg.red = 221 * 255;
3790     bg.green = 226 * 255;
3791     bg.blue = 228 * 255;
3792
3793     topic_header = welcome_topic_header_new(header);
3794     gtk_box_pack_start(GTK_BOX(topic_vb), topic_header, FALSE, FALSE, 0);
3795
3796     layout_vb = gtk_vbox_new(FALSE, 5);
3797     gtk_container_border_width(GTK_CONTAINER(layout_vb), 10);
3798     gtk_box_pack_start(GTK_BOX(topic_vb), layout_vb, FALSE, FALSE, 0);
3799
3800     /* colorize vbox (we need an event box for this!) */
3801     get_color(&bg);
3802     topic_eb = gtk_event_box_new();
3803     gtk_container_add(GTK_CONTAINER(topic_eb), topic_vb);
3804 #if GTK_MAJOR_VERSION >= 2
3805     gtk_widget_modify_bg(topic_eb, GTK_STATE_NORMAL, &bg);
3806 #endif
3807     *to_fill = layout_vb;
3808
3809     return topic_eb;
3810 }
3811
3812
3813 #if GTK_MAJOR_VERSION >= 2
3814 static gboolean
3815 welcome_link_enter_cb(GtkWidget *widget _U_, GdkEventCrossing *event _U_, gpointer user_data)
3816 {
3817     gchar *message;
3818     GtkWidget *w = user_data;
3819
3820     message = g_strdup_printf("<span foreground='blue' underline='single'>%s</span>", OBJECT_GET_DATA(w,"TEXT"));
3821 #if GTK_MAJOR_VERSION >= 2
3822     gtk_label_set_markup(GTK_LABEL(w), message);
3823 #endif
3824     g_free(message);
3825
3826     return FALSE;
3827 }
3828
3829 static gboolean
3830 welcome_link_leave_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer user_data)
3831 {
3832     gchar *message;
3833     GtkWidget *w = user_data;
3834
3835     message = g_strdup_printf("<span foreground='blue'>%s</span>", OBJECT_GET_DATA(w,"TEXT"));
3836 #if GTK_MAJOR_VERSION >= 2
3837     gtk_label_set_markup(GTK_LABEL(w), message);
3838 #endif
3839     g_free(message);
3840
3841     return FALSE;
3842 }
3843 #endif
3844
3845
3846 static gboolean
3847 welcome_link_press_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_) {
3848
3849     g_warning("TBD: link pressed");
3850
3851     return FALSE;
3852 }
3853
3854 GtkWidget *
3855 welcome_link_new(const gchar *text, GtkWidget **label /*, void *callback, void *private_data */)
3856 {
3857     gchar *message;
3858     GtkWidget *w;
3859     GtkWidget *eb;
3860
3861 #if GTK_MAJOR_VERSION < 2
3862     message = g_strdup(text);
3863 #else
3864     message = g_strdup_printf("<span foreground='blue'>%s</span>", text);
3865 #endif
3866     w = gtk_label_new(message);
3867     *label = w;
3868 #if GTK_MAJOR_VERSION >= 2
3869     gtk_label_set_markup(GTK_LABEL(w), message);
3870 #endif
3871     g_free(message);
3872
3873         /* event box */
3874     eb = gtk_event_box_new();
3875     gtk_container_add(GTK_CONTAINER(eb), w);
3876
3877 #if GTK_MAJOR_VERSION >= 2
3878     SIGNAL_CONNECT(eb, "enter-notify-event", welcome_link_enter_cb, w);
3879     SIGNAL_CONNECT(eb, "leave-notify-event", welcome_link_leave_cb, w);
3880 #endif
3881     SIGNAL_CONNECT(eb, "button-press-event", welcome_link_press_cb, w);
3882
3883     /* XXX - memleak */
3884     OBJECT_SET_DATA(w, "TEXT", g_strdup(text));
3885
3886     return eb;
3887 }
3888
3889 GtkWidget *
3890 welcome_filename_link_new(const char *filename, GtkWidget **label)
3891 {
3892     GString             *str;
3893     GtkWidget   *w;
3894     const unsigned int max = 60;
3895
3896
3897     str = g_string_new(filename);
3898
3899     if(str->len > max) {
3900         g_string_erase(str, 0, str->len-max /*cut*/);
3901         g_string_prepend(str, "... ");
3902     }
3903
3904     w = welcome_link_new(str->str, label);
3905
3906     g_string_free(str, TRUE);
3907
3908     return w;
3909 }
3910
3911
3912 GtkWidget *
3913 welcome_if_new(const char *if_name, GdkColor *topic_bg, gboolean active)
3914 {
3915     GtkWidget *interface_hb;
3916     GtkWidget *w;
3917     GtkWidget *label;
3918     GtkTooltips *tooltips;
3919     GString   *message;
3920
3921
3922     tooltips = gtk_tooltips_new();
3923
3924     interface_hb = gtk_hbox_new(FALSE, 5);
3925
3926     w = welcome_link_new("START", &label);
3927     gtk_tooltips_set_tip(tooltips, w, "Immediately start a capture on this interface", NULL);
3928 #if GTK_MAJOR_VERSION >= 2
3929     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
3930 #endif
3931     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3932     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3933
3934     w = welcome_link_new("OPTIONS", &label);
3935     gtk_tooltips_set_tip(tooltips, w, "Show the capture options of this interface", NULL);
3936 #if GTK_MAJOR_VERSION >= 2
3937     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
3938 #endif
3939     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3940     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3941
3942     w = welcome_link_new("DETAILS", &label);
3943     gtk_tooltips_set_tip(tooltips, w, "Show detailed information about this interface", NULL);
3944 #if GTK_MAJOR_VERSION >= 2
3945     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, topic_bg);
3946 #endif
3947     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
3948     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3949
3950     message = g_string_new(if_name);
3951
3952     /* truncate string if it's too long */
3953     if(message->len > 38) {
3954         g_string_truncate(message, 35);
3955         g_string_append  (message, " ...");
3956     }
3957 #if GTK_MAJOR_VERSION >= 2
3958     /* if this is the "active" interface, display it bold */
3959     if(active) {
3960         g_string_prepend(message, "<span weight=\"bold\">");
3961         g_string_append (message, "</span>");
3962         }
3963 #endif
3964     w = gtk_label_new(message->str);
3965 #if GTK_MAJOR_VERSION >= 2
3966     gtk_label_set_markup(GTK_LABEL(w), message->str);
3967 #endif
3968     g_string_free(message, TRUE);
3969
3970     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
3971     gtk_box_pack_start(GTK_BOX(interface_hb), w, FALSE, FALSE, 0);
3972
3973     return interface_hb;
3974 }
3975
3976 /* XXX - the layout has to be improved */
3977 GtkWidget *
3978 welcome_new(void)
3979 {
3980     GtkWidget *welcome_scrollw;
3981     GtkWidget *welcome_vb;
3982     GtkWidget *welcome_hb;
3983     GtkWidget *column_vb;
3984     GtkWidget *item_hb;
3985     GtkWidget *w;
3986     GtkWidget *label;
3987     GtkWidget *header;
3988     GtkWidget *topic_vb;
3989     GtkWidget *topic_to_fill;
3990     GtkWidget *interface_hb;
3991     GdkColor  topic_bg;
3992
3993
3994     /* topic content background color */
3995     topic_bg.pixel = 0;
3996     topic_bg.red = 221 * 255;
3997     topic_bg.green = 226 * 255;
3998     topic_bg.blue = 228 * 255;
3999
4000     welcome_scrollw = scrolled_window_new(NULL, NULL);
4001
4002     welcome_vb = gtk_vbox_new(FALSE, 0);
4003
4004     /* header */
4005     header = welcome_header_new();
4006     gtk_box_pack_start(GTK_BOX(welcome_vb), header, FALSE, FALSE, 0);
4007
4008     /* content */
4009     welcome_hb = gtk_hbox_new(FALSE, 10);
4010     gtk_container_border_width(GTK_CONTAINER(welcome_hb), 10);
4011     gtk_box_pack_start(GTK_BOX(welcome_vb), welcome_hb, TRUE, TRUE, 0);
4012
4013     /* column capture */
4014     column_vb = gtk_vbox_new(FALSE, 10);
4015     gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
4016
4017     /* capture topic */
4018     topic_vb = welcome_topic_new("Capture", &topic_to_fill);
4019     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
4020
4021 #ifdef HAVE_LIBPCAP
4022     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_INTERFACES,
4023         "Interfaces...",
4024         "Interface Life List",
4025                 "Show a life list of the available capture interfaces",
4026         GTK_SIGNAL_FUNC(capture_if_cb), NULL);
4027     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4028 #endif
4029
4030     w = gtk_label_new("Available Interfaces:");
4031     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
4032     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
4033
4034     interface_hb = welcome_if_new("Generic dialup adapter", &topic_bg, FALSE);
4035     gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
4036
4037     /* Marvell interface (currently "active") */
4038     interface_hb = welcome_if_new("Marvell Gigabit Ethernet Controller", &topic_bg, TRUE);
4039     gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
4040
4041     /* Wireless interface */
4042     interface_hb = welcome_if_new("Intel(R) PRO/Wireless 3945ABG Network Connection", &topic_bg, FALSE);
4043     gtk_box_pack_start(GTK_BOX(topic_to_fill), interface_hb, FALSE, FALSE, 0);
4044
4045
4046     /* capture help topic */
4047     topic_vb = welcome_topic_new("Capture Help", &topic_to_fill);
4048     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
4049
4050 #ifdef HAVE_LIBPCAP
4051     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
4052         "Setup",
4053                 "How To: Setup a Capture",
4054                 "How To: Setup a Capture (online from the Wiki)",
4055         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
4056     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4057
4058     item_hb = welcome_item(WIRESHARK_STOCK_CAPTURE_START,
4059         "Examples",
4060                 "Capture Filter Examples",
4061                 "Capture Filter Examples (online from the Wiki)",
4062         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
4063     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4064 #endif
4065
4066     /* fill bottom space */
4067     w = gtk_label_new("");
4068     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
4069
4070
4071     /* column files */
4072     topic_vb = welcome_topic_new("Files", &topic_to_fill);
4073     gtk_box_pack_start(GTK_BOX(welcome_hb), topic_vb, TRUE, TRUE, 0);
4074
4075     item_hb = welcome_item(GTK_STOCK_OPEN,
4076         "Open...",
4077         "Open a Capture File",
4078                 "Open a previously captured file",
4079         GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
4080     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4081
4082     item_hb = welcome_item(GTK_STOCK_OPEN,
4083         "Examples",
4084         "Download Examples",
4085                 "Download Example Capture Files (from the Wiki)",
4086         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
4087     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4088
4089     w = gtk_label_new("Recent Files:");
4090     gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
4091     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 5);
4092
4093     w = welcome_link_new("C:\\Testfiles\\hello.pcap", &label);
4094 #if GTK_MAJOR_VERSION >= 2
4095     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
4096 #endif
4097     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
4098     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
4099
4100     w = welcome_filename_link_new("C:\\Testfiles\\hello2.pcap", &label);
4101 #if GTK_MAJOR_VERSION >= 2
4102     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
4103 #endif
4104     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
4105     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
4106
4107     w = welcome_filename_link_new(
4108                 "C:\\Testfiles\\to avoid screen garbage\\Unfortunately this is a very long filename which had to be truncated.pcap",
4109                 &label);
4110 #if GTK_MAJOR_VERSION >= 2
4111     gtk_widget_modify_bg(w, GTK_STATE_NORMAL, &topic_bg);
4112 #endif
4113     gtk_misc_set_alignment (GTK_MISC(label), 0.0, 0.0);
4114     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, FALSE, FALSE, 0);
4115
4116     w = gtk_label_new("");
4117     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
4118
4119
4120     /* column online */
4121     column_vb = gtk_vbox_new(FALSE, 10);
4122     gtk_box_pack_start(GTK_BOX(welcome_hb), column_vb, TRUE, TRUE, 0);
4123
4124     /* topic online */
4125     topic_vb = welcome_topic_new("Online", &topic_to_fill);
4126     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
4127
4128 #if (GLIB_MAJOR_VERSION >= 2)
4129     item_hb = welcome_item(WIRESHARK_STOCK_WEB_SUPPORT,
4130         "Help",
4131         "Show the User's Guide",
4132                 "Show the User's Guide (local version, if available)",
4133         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_USERGUIDE));
4134     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4135
4136     item_hb = welcome_item(GTK_STOCK_HOME,
4137         "Home",
4138         "Projects Home Page",
4139                 "Visit www.wireshark.org, the project's home page",
4140         GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
4141     gtk_box_pack_start(GTK_BOX(topic_to_fill), item_hb, FALSE, FALSE, 5);
4142 #endif
4143
4144     /* topic updates */
4145     topic_vb = welcome_topic_new("Updates", &topic_to_fill);
4146     gtk_box_pack_start(GTK_BOX(column_vb), topic_vb, TRUE, TRUE, 0);
4147
4148     w = gtk_label_new("No updates available!");
4149     gtk_box_pack_start(GTK_BOX(topic_to_fill), w, TRUE, TRUE, 0);
4150
4151
4152     /* the end */
4153     gtk_widget_show_all(welcome_vb);
4154
4155     gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
4156                                           welcome_vb);
4157     gtk_widget_show_all(welcome_scrollw);
4158
4159     return welcome_scrollw;
4160 }
4161 #else
4162 static GtkWidget *
4163 welcome_new(void)
4164 {
4165     /* this is just a dummy to fill up window space, simply showing nothing */
4166     return scrolled_window_new(NULL, NULL);
4167 }
4168 #endif
4169
4170
4171
4172 /*
4173  * XXX - this doesn't appear to work with the paned widgets in
4174  * GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
4175  * and the other pane doesn't grow to take up the rest of the pane.
4176  * It does appear to work with GTK+ 2.x.
4177  */
4178 void
4179 main_widgets_show_or_hide(void)
4180 {
4181     gboolean main_second_pane_show;
4182
4183     if (recent.main_toolbar_show) {
4184         gtk_widget_show(main_tb);
4185     } else {
4186         gtk_widget_hide(main_tb);
4187     }
4188
4189     /*
4190      * Show the status hbox if either:
4191      *
4192      *    1) we're showing the filter toolbar and we want it in the status
4193      *       line
4194      *
4195      * or
4196      *
4197      *    2) we're showing the status bar.
4198      */
4199     if ((recent.filter_toolbar_show && prefs.filter_toolbar_show_in_statusbar) ||
4200          recent.statusbar_show) {
4201         gtk_widget_show(stat_hbox);
4202     } else {
4203         gtk_widget_hide(stat_hbox);
4204     }
4205
4206     if (recent.statusbar_show) {
4207         gtk_widget_show(status_pane_left);
4208     } else {
4209         gtk_widget_hide(status_pane_left);
4210     }
4211
4212     if (recent.filter_toolbar_show) {
4213         gtk_widget_show(filter_tb);
4214     } else {
4215         gtk_widget_hide(filter_tb);
4216     }
4217
4218 #ifdef HAVE_AIRPCAP
4219     if (recent.airpcap_toolbar_show) {
4220         gtk_widget_show(airpcap_tb);
4221     } else {
4222         gtk_widget_hide(airpcap_tb);
4223     }
4224 #endif
4225
4226     if (recent.packet_list_show && have_capture_file) {
4227         gtk_widget_show(pkt_scrollw);
4228     } else {
4229         gtk_widget_hide(pkt_scrollw);
4230     }
4231
4232     if (recent.tree_view_show && have_capture_file) {
4233         gtk_widget_show(tv_scrollw);
4234     } else {
4235         gtk_widget_hide(tv_scrollw);
4236     }
4237
4238     if (recent.byte_view_show && have_capture_file) {
4239         gtk_widget_show(byte_nb_ptr);
4240     } else {
4241         gtk_widget_hide(byte_nb_ptr);
4242     }
4243
4244     if (have_capture_file) {
4245         gtk_widget_show(main_first_pane);
4246     } else {
4247         gtk_widget_hide(main_first_pane);
4248     }
4249
4250     /*
4251      * Is anything in "main_second_pane" visible?
4252      * If so, show it, otherwise hide it.
4253      */
4254     main_second_pane_show = FALSE;
4255     gtk_container_foreach(GTK_CONTAINER(main_second_pane), is_widget_visible,
4256                           &main_second_pane_show);
4257     if (main_second_pane_show) {
4258         gtk_widget_show(main_second_pane);
4259     } else {
4260         gtk_widget_hide(main_second_pane);
4261     }
4262
4263     if (!have_capture_file) {
4264         if(welcome_pane) {
4265             gtk_widget_show(welcome_pane);
4266         }
4267     } else {
4268         gtk_widget_hide(welcome_pane);
4269     }
4270
4271     /* workaround for bug in GtkCList to ensure packet list scrollbar is updated */
4272     packet_list_freeze ();
4273     packet_list_thaw ();
4274 }
4275
4276
4277 #if GTK_MAJOR_VERSION >= 2
4278 /* called, when the window state changes (minimized, maximized, ...) */
4279 static int
4280 window_state_event_cb (GtkWidget *widget _U_,
4281                        GdkEvent *event,
4282                        gpointer  data _U_)
4283 {
4284     GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
4285
4286     if( (event->type) == (GDK_WINDOW_STATE)) {
4287         if(!(new_window_state & GDK_WINDOW_STATE_ICONIFIED)) {
4288             /* we might have dialogs popped up while we where iconified,
4289                show em now */
4290             display_queued_messages();
4291         }
4292     }
4293     return FALSE;
4294 }
4295 #endif
4296
4297 #ifdef HAVE_AIRPCAP
4298 /*
4299  * Changed callback for the channel combobox
4300  */
4301 static void
4302 airpcap_toolbar_channel_changed_cb(GtkWidget *w _U_, gpointer data)
4303 {
4304   const gchar *s;
4305   ULONG ch_freq;
4306
4307   if ((data != NULL) && (w != NULL) && change_airpcap_settings) {
4308         s = gtk_entry_get_text(GTK_ENTRY(w));
4309     if ((g_ascii_strcasecmp("",s))) {
4310       ch_freq = airpcap_get_frequency_from_str(s);
4311       if (airpcap_if_active != NULL) {
4312                 airpcap_if_active->channelInfo.Frequency = ch_freq;
4313                 airpcap_update_channel_offset_cb(airpcap_if_active, ch_freq, GTK_WIDGET(data));
4314       }
4315     }
4316   }
4317 }
4318
4319 /*
4320  * Changed callback for the channel offset combobox
4321  */
4322 static void
4323 on_channel_offset_cb_changed(GtkWidget *w _U_, gpointer data)
4324 {
4325     const gchar *s;
4326     gchar offset;
4327
4328     if ((data != NULL) && (w != NULL) && change_airpcap_settings)
4329     {
4330         s = gtk_entry_get_text(GTK_ENTRY(w));
4331         if ((g_ascii_strcasecmp("",s)))
4332         {
4333             if (airpcap_if_active != NULL)
4334             {
4335                 sscanf(s,"%d",&offset);
4336                 airpcap_if_active->channelInfo.ExtChannel = offset;
4337                 if (change_airpcap_settings != NULL)
4338                 {
4339                     airpcap_update_frequency_and_offset(airpcap_if_active);
4340                 }
4341             }
4342         }
4343     }
4344 }
4345
4346 /*
4347  * Callback for the wrong crc combo
4348  */
4349 static void
4350 airpcap_toolbar_wrong_crc_combo_cb(GtkWidget *entry, gpointer user_data)
4351 {
4352   gchar ebuf[AIRPCAP_ERRBUF_SIZE];
4353   PAirpcapHandle ad;
4354
4355   if( !block_toolbar_signals && (airpcap_if_active != NULL)) {
4356     ad = airpcap_if_open(airpcap_if_active->name, ebuf);
4357
4358     if (ad) {
4359       airpcap_if_active->CrcValidationOn = airpcap_get_validation_type(gtk_entry_get_text(GTK_ENTRY(entry)));
4360       airpcap_if_set_fcs_validation(ad,airpcap_if_active->CrcValidationOn);
4361       /* Save configuration */
4362       airpcap_if_store_cur_config_as_adapter_default(ad);
4363       airpcap_if_close(ad);
4364     }
4365   }
4366 }
4367
4368 void
4369 airpcap_toolbar_encryption_cb(GtkWidget *entry, gpointer user_data)
4370 {
4371   /* We need to directly access the .ddl functions here... */
4372   gchar ebuf[AIRPCAP_ERRBUF_SIZE];
4373   PAirpcapHandle ad;
4374
4375  gint n = 0;
4376   gint i = 0;
4377   airpcap_if_info_t* curr_if = NULL;
4378
4379   /* Apply changes to the current adapter */
4380   if( (airpcap_if_active != NULL)) {
4381     ad = airpcap_if_open(airpcap_if_active->name, ebuf);
4382
4383     if(ad) {
4384       if(airpcap_if_active->DecryptionOn == AIRPCAP_DECRYPTION_ON) {
4385         airpcap_if_active->DecryptionOn = AIRPCAP_DECRYPTION_OFF;
4386         airpcap_if_set_decryption_state(ad,airpcap_if_active->DecryptionOn);
4387         /* Save configuration */
4388         if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
4389           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
4390         }
4391         airpcap_if_close(ad);
4392       } else {
4393         airpcap_if_active->DecryptionOn = AIRPCAP_DECRYPTION_ON;
4394         airpcap_if_set_decryption_state(ad,airpcap_if_active->DecryptionOn);
4395         /* Save configuration */
4396         if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
4397           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
4398         }
4399         airpcap_if_close(ad);
4400       }
4401     }
4402   } else {
4403     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "No active AirPcap Adapter selected!");
4404     return;
4405   }
4406
4407   if (!(airpcap_if_list == NULL)){
4408   n = g_list_length(airpcap_if_list);
4409
4410   /* The same kind of settings should be propagated to all the adapters */
4411   /* Apply this change to all the adapters !!! */
4412   for(i = 0; i < n; i++) {
4413     curr_if = (airpcap_if_info_t*)g_list_nth_data(airpcap_if_list,i);
4414
4415     if( (curr_if != NULL) && (curr_if != airpcap_if_selected) ) {
4416       ad = airpcap_if_open(curr_if->name, ebuf);
4417       if(ad) {
4418         curr_if->DecryptionOn = airpcap_if_selected->DecryptionOn;
4419         airpcap_if_set_decryption_state(ad,curr_if->DecryptionOn);
4420         /* Save configuration for the curr_if */
4421         if(!airpcap_if_store_cur_config_as_adapter_default(ad)) {
4422           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Cannot save configuration!!!\nRemember that in order to store the configuration in the registry you have to:\n\n- Close all the airpcap-based applications.\n- Be sure to have administrative privileges.");
4423         }
4424         airpcap_if_close(ad);
4425       }
4426     }
4427   }
4428   } else {
4429     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "AirPcap Adapter Error!");
4430     return;
4431   }
4432 }
4433
4434 /*
4435  * Callback for the Advanced Wireless Settings button
4436  */
4437 static void
4438 toolbar_display_airpcap_advanced_cb(GtkWidget *w, gpointer data)
4439 {
4440     int *from_widget;
4441
4442     from_widget = (gint*)g_malloc(sizeof(gint));
4443     *from_widget = AIRPCAP_ADVANCED_FROM_TOOLBAR;
4444     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_ADVANCED_FROM_KEY,from_widget);
4445
4446     display_airpcap_advanced_cb(w,data);
4447 }
4448
4449 /*
4450  * Callback for the Decryption Key Management button
4451  */
4452 static void
4453 toolbar_display_airpcap_key_management_cb(GtkWidget *w, gpointer data)
4454 {
4455     int *from_widget;
4456
4457     from_widget = (gint*)g_malloc(sizeof(gint));
4458     *from_widget = AIRPCAP_ADVANCED_FROM_TOOLBAR;
4459     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_ADVANCED_FROM_KEY,from_widget);
4460
4461     display_airpcap_key_management_cb(w,data);
4462 }
4463 #endif /* HAVE_AIRPCAP */
4464
4465 #if GTK_MAJOR_VERSION >= 2
4466 #define NO_SHIFT_MOD_MASK (GDK_MODIFIER_MASK & ~(GDK_SHIFT_MASK|GDK_LOCK_MASK))
4467 static int
4468 top_level_key_pressed_cb(GtkCTree *ctree _U_, GdkEventKey *event, gpointer user_data _U_)
4469 {
4470     if (event->keyval == GDK_F8) {
4471         packet_list_next();
4472         return TRUE;
4473     } else if (event->keyval == GDK_F7) {
4474         packet_list_prev();
4475         return TRUE;
4476     } else if (event->state & NO_SHIFT_MOD_MASK) {
4477         return FALSE; /* Skip control, alt, and other modifiers */
4478     /*
4479      * A comment in gdkkeysyms.h says that it's autogenerated from
4480      * freedesktop.org/x.org's keysymdef.h.  Although the GDK docs
4481      * don't explicitly say so, isprint() should work as expected
4482      * for values < 127.
4483      */
4484     } else if (isascii(event->keyval) && isprint(event->keyval)) {
4485         /* Forward the keypress on to the display filter entry */
4486         if (main_display_filter_widget && !gtk_widget_is_focus(main_display_filter_widget)) {
4487             gtk_window_set_focus(GTK_WINDOW(top_level), main_display_filter_widget);
4488             gtk_editable_set_position(GTK_EDITABLE(main_display_filter_widget), -1);
4489         }
4490         return FALSE;
4491     }
4492     return FALSE;
4493 }
4494 #endif
4495
4496 static void
4497 create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
4498 {
4499     GtkWidget
4500                   *filter_bt, *filter_cm, *filter_te,
4501                   *filter_add_expr_bt,
4502                   *filter_apply,
4503                   *filter_reset;
4504     GList         *dfilter_list = NULL;
4505     GtkTooltips   *tooltips;
4506
4507     GtkAccelGroup *accel;
4508     gchar         *title;
4509
4510 #ifdef HAVE_AIRPCAP
4511     GtkWidget     *key_management_bt = NULL,
4512 #if GTK_MAJOR_VERSION >= 2 /* For some reason this button's action crashes under GTK 1. */
4513                   *advanced_bt = NULL,
4514 #endif
4515                   *channel_lb = NULL,
4516                   *channel_cm = NULL,
4517                   *channel_offset_lb = NULL,
4518                   *channel_offset_cb = NULL,
4519                   *wrong_crc_lb = NULL,
4520                   *wrong_crc_cm = NULL;
4521
4522     GtkWidget     *enable_decryption_lb;
4523     GtkWidget     *enable_decryption_cb;
4524     GList         *enable_decryption_cb_items = NULL;
4525     GtkWidget     *enable_decryption_en;
4526
4527     GList         *channel_list = NULL;
4528     GList         *linktype_list = NULL;
4529     GList         *link_list = NULL;
4530     GtkTooltips   *airpcap_tooltips;
4531     /* gchar      *if_label_text; */
4532     gint          *from_widget = NULL;
4533     gchar         *chan_str;
4534 #endif
4535
4536     /* Display filter construct dialog has an Apply button, and "OK" not
4537        only sets our text widget, it activates it (i.e., it causes us to
4538        filter the capture). */
4539     static construct_args_t args = {
4540         "Wireshark: Display Filter",
4541         TRUE,
4542         TRUE,
4543         FALSE
4544     };
4545
4546     /* use user-defined title if preference is set */
4547     title = create_user_window_title("The Wireshark Network Analyzer");
4548
4549     /* Main window */
4550     top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
4551     g_free(title);
4552
4553     tooltips = gtk_tooltips_new();
4554
4555 #ifdef HAVE_AIRPCAP
4556     airpcap_tooltips = gtk_tooltips_new();
4557 #endif
4558
4559 #ifdef _WIN32
4560 #if GTK_MAJOR_VERSION < 2
4561     /* has to be done, after top_level window is created */
4562     app_font_gtk1_init(top_level);
4563 #endif
4564 #endif
4565
4566     gtk_widget_set_name(top_level, "main window");
4567     SIGNAL_CONNECT(top_level, "delete_event", main_window_delete_event_cb,
4568                    NULL);
4569 #if GTK_MAJOR_VERSION >= 2
4570     SIGNAL_CONNECT(GTK_OBJECT(top_level), "window_state_event",
4571                          G_CALLBACK (window_state_event_cb), NULL);
4572     SIGNAL_CONNECT(GTK_OBJECT(top_level), "key-press-event",
4573                          G_CALLBACK (top_level_key_pressed_cb), NULL );
4574 #endif
4575
4576     gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
4577
4578     /* Container for menu bar, toolbar(s), paned windows and progress/info box */
4579     main_vbox = gtk_vbox_new(FALSE, 1);
4580     gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
4581     gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
4582     gtk_widget_show(main_vbox);
4583
4584     /* Menu bar */
4585     menubar = main_menu_new(&accel);
4586     gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
4587     gtk_widget_show(menubar);
4588
4589     /* Main Toolbar */
4590     main_tb = toolbar_new();
4591     gtk_widget_show (main_tb);
4592
4593     /* Packet list */
4594     pkt_scrollw = packet_list_new(prefs);
4595     WIDGET_SET_SIZE(packet_list, -1, pl_size);
4596     gtk_widget_show(pkt_scrollw);
4597
4598     /* Tree view */
4599     tv_scrollw = main_tree_view_new(prefs, &tree_view);
4600     WIDGET_SET_SIZE(tv_scrollw, -1, tv_size);
4601     gtk_widget_show(tv_scrollw);
4602
4603 #if GTK_MAJOR_VERSION < 2
4604     SIGNAL_CONNECT(tree_view, "tree-select-row", tree_view_select_row_cb, NULL);
4605     SIGNAL_CONNECT(tree_view, "tree-unselect-row", tree_view_unselect_row_cb,
4606                    NULL);
4607 #else
4608     SIGNAL_CONNECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
4609                    "changed", tree_view_selection_changed_cb, NULL);
4610 #endif
4611     SIGNAL_CONNECT(tree_view, "button_press_event", popup_menu_handler,
4612                    OBJECT_GET_DATA(popup_menu_object, PM_TREE_VIEW_KEY));
4613     gtk_widget_show(tree_view);
4614
4615     /* Byte view. */
4616     byte_nb_ptr = byte_view_new();
4617     WIDGET_SET_SIZE(byte_nb_ptr, -1, bv_size);
4618     gtk_widget_show(byte_nb_ptr);
4619
4620     SIGNAL_CONNECT(byte_nb_ptr, "button_press_event", popup_menu_handler,
4621                    OBJECT_GET_DATA(popup_menu_object, PM_HEXDUMP_KEY));
4622
4623
4624     /* Panes for the packet list, tree, and byte view */
4625     main_pane_v1 = gtk_vpaned_new();
4626     gtk_widget_show(main_pane_v1);
4627     main_pane_v2 = gtk_vpaned_new();
4628     gtk_widget_show(main_pane_v2);
4629     main_pane_h1 = gtk_hpaned_new();
4630     gtk_widget_show(main_pane_h1);
4631     main_pane_h2 = gtk_hpaned_new();
4632     gtk_widget_show(main_pane_h2);
4633
4634 #ifdef HAVE_AIRPCAP
4635     /* airpcap toolbar */
4636 #if GTK_MAJOR_VERSION < 2
4637     airpcap_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
4638                                GTK_TOOLBAR_BOTH);
4639 #else
4640     airpcap_tb = gtk_toolbar_new();
4641     gtk_toolbar_set_orientation(GTK_TOOLBAR(airpcap_tb),
4642                                 GTK_ORIENTATION_HORIZONTAL);
4643 #endif /* GTK_MAJOR_VERSION */
4644     gtk_widget_show(airpcap_tb);
4645
4646     /* Interface Label */
4647     /*if(airpcap_if_active != NULL) {
4648         if_label_text = g_strdup_printf("%s %s\t","Current Wireless Interface: #",airpcap_get_if_string_number(airpcap_if_active));
4649         interface_lb = gtk_label_new(if_label_text);
4650         g_free(if_label_text);
4651     } else {
4652         interface_lb = gtk_label_new("No Wireless Interface Found  ");
4653     }*/
4654
4655     /* Add the label to the toolbar */
4656     /*gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), interface_lb,
4657                               "Current Wireless Interface", "Private");
4658     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_INTERFACE_KEY,interface_lb);
4659     gtk_widget_show(interface_lb);
4660     gtk_toolbar_insert_space(GTK_TOOLBAR(airpcap_tb),1);*/
4661
4662
4663     /* Create the "802.11 Channel:" label */
4664     channel_lb = gtk_label_new("802.11 Channel: ");
4665     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_LABEL_KEY,channel_lb);
4666     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_lb,
4667                               "Current 802.11 Channel", "Private");
4668     gtk_widget_show(channel_lb);
4669
4670     WIDGET_SET_SIZE(channel_lb, 85, 28);
4671
4672     /* Create the channel combo box */
4673     channel_cm = gtk_combo_new();
4674     gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(channel_cm)->entry),FALSE);
4675     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_KEY,channel_cm);
4676
4677     if (airpcap_if_active != NULL && airpcap_if_active->pSupportedChannels != NULL && airpcap_if_active->numSupportedChannels > 0){
4678         guint i = 0;
4679         for (; i<airpcap_if_active->numSupportedChannels; i++){
4680             channel_list = g_list_append(channel_list, ieee80211_mhz_to_str(airpcap_if_active->pSupportedChannels[i].Frequency));
4681         }
4682         gtk_combo_set_popdown_strings( GTK_COMBO(channel_cm), channel_list);
4683         airpcap_free_channel_combo_list(channel_list);
4684     }
4685
4686     gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(channel_cm)->entry),
4687                 "Change the 802.11 RF channel", NULL);
4688
4689     WIDGET_SET_SIZE(channel_cm, 120, 28);
4690
4691     if(airpcap_if_active != NULL) {
4692         chan_str = ieee80211_mhz_to_str(airpcap_if_active->channelInfo.Frequency);
4693         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cm)->entry), chan_str);
4694         g_free(chan_str);
4695     }
4696     else {
4697         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_cm)->entry),"");
4698     }
4699     gtk_widget_show(channel_cm);
4700
4701     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_cm,
4702                               "802.11 Channel", "Private");
4703
4704     /* gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb)); */
4705
4706     /* Create the "Channel Offset:" label */
4707     channel_offset_lb = gtk_label_new("Channel Offset: ");
4708     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_CHANNEL_OFFSET_LABEL_KEY,channel_offset_lb);
4709     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_offset_lb,
4710                               "Current 802.11 Channel Offset", "Private");
4711     gtk_widget_show(channel_offset_lb);
4712
4713     WIDGET_SET_SIZE(channel_offset_lb, 80, 28);
4714
4715     /* Start: Channel offset combo box */
4716     channel_offset_cb = gtk_combo_new();
4717     gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(channel_offset_cb)->entry),FALSE);
4718     OBJECT_SET_DATA(airpcap_tb, AIRPCAP_TOOLBAR_CHANNEL_OFFSET_KEY, channel_offset_cb);
4719
4720     if(airpcap_if_active != NULL){
4721                 airpcap_update_channel_offset_cb(airpcap_if_active, airpcap_if_active->channelInfo.Frequency, channel_offset_cb);
4722                 airpcap_update_channel_offset_combo_entry(channel_offset_cb, airpcap_if_active->channelInfo.ExtChannel);
4723     } else {
4724         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(channel_offset_cb)->entry),"");
4725     }
4726
4727     gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(channel_offset_cb)->entry),
4728                 "Change channel offset", NULL);
4729
4730     WIDGET_SET_SIZE(channel_offset_cb, 50, 28);
4731
4732     gtk_widget_show(channel_offset_cb);
4733
4734     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), channel_offset_cb,
4735                               "802.11 Channel Offset", "Private");
4736
4737     gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4738
4739     /* callback for channel combo box */
4740     SIGNAL_CONNECT(GTK_COMBO(channel_cm)->entry,"changed", airpcap_toolbar_channel_changed_cb, channel_offset_cb);
4741     /* callback for channel offset combo box */
4742     SIGNAL_CONNECT(GTK_COMBO(channel_offset_cb)->entry,"changed", on_channel_offset_cb_changed, channel_offset_cb);
4743     /* End: Channel offset combo box */
4744
4745     /* Wrong CRC Label */
4746     wrong_crc_lb = gtk_label_new(" FCS Filter: ");
4747     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_FCS_FILTER_LABEL_KEY,wrong_crc_lb);
4748     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), wrong_crc_lb,
4749                               "", "Private");
4750     gtk_widget_show(wrong_crc_lb);
4751
4752     /* Wrong CRC combo */
4753     wrong_crc_cm = gtk_combo_new();
4754     gtk_editable_set_editable(GTK_EDITABLE(GTK_COMBO(wrong_crc_cm)->entry),FALSE);
4755     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_FCS_FILTER_KEY,wrong_crc_cm);
4756     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), wrong_crc_cm,
4757                               "", "Private");
4758
4759     WIDGET_SET_SIZE(wrong_crc_cm, 100, -1);
4760
4761     linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_ALL);
4762     linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_CORRECT);
4763     linktype_list = g_list_append(linktype_list, AIRPCAP_VALIDATION_TYPE_NAME_CORRUPT);
4764
4765     gtk_combo_set_popdown_strings( GTK_COMBO(wrong_crc_cm), linktype_list) ;
4766     g_list_free(linktype_list);
4767     gtk_tooltips_set_tip(airpcap_tooltips, GTK_WIDGET(GTK_COMBO(wrong_crc_cm)->entry),
4768         "Select the 802.11 FCS filter that the wireless adapter will apply.",
4769         NULL);
4770
4771     if(airpcap_if_active != NULL)
4772         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wrong_crc_cm)->entry), airpcap_get_validation_name(airpcap_if_active->CrcValidationOn));
4773     else
4774         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(wrong_crc_cm)->entry),"");
4775
4776     SIGNAL_CONNECT(GTK_COMBO(wrong_crc_cm)->entry,"changed",airpcap_toolbar_wrong_crc_combo_cb,airpcap_tb);
4777     gtk_widget_show(wrong_crc_cm);
4778
4779     gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4780
4781     /* Decryption mode combo box */
4782     enable_decryption_lb = gtk_label_new ("Decryption Mode: ");
4783     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_LABEL_KEY,enable_decryption_lb);
4784     gtk_widget_set_name (enable_decryption_lb, "enable_decryption_lb");
4785     gtk_widget_show (enable_decryption_lb);
4786     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), enable_decryption_lb,
4787     NULL, "Private");
4788
4789     enable_decryption_cb = gtk_combo_new ();
4790     gtk_widget_set_name (enable_decryption_cb, "enable_decryption_cb");
4791     gtk_widget_show (enable_decryption_cb);
4792     WIDGET_SET_SIZE (enable_decryption_cb, 83, -1);
4793     update_decryption_mode_list(enable_decryption_cb);
4794
4795     enable_decryption_en = GTK_COMBO (enable_decryption_cb)->entry;
4796     gtk_widget_set_name (enable_decryption_en, "enable_decryption_en");
4797     gtk_widget_show (enable_decryption_en);
4798     gtk_editable_set_editable (GTK_EDITABLE (enable_decryption_en), FALSE);
4799     GTK_WIDGET_UNSET_FLAGS (enable_decryption_en, GTK_CAN_FOCUS);
4800
4801     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), enable_decryption_cb,
4802         "Choose a Decryption Mode", "Private");
4803
4804     /* Set current decryption mode!!!! */
4805     update_decryption_mode_cm(enable_decryption_cb);
4806     SIGNAL_CONNECT (enable_decryption_en, "changed",on_enable_decryption_en_changed, airpcap_tb);
4807     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_DECRYPTION_KEY,enable_decryption_cb);
4808
4809     gtk_toolbar_append_space(GTK_TOOLBAR(airpcap_tb));
4810
4811 #if GTK_MAJOR_VERSION >= 2 /* For some reason this button's action crashes under GTK 1. */
4812     /* Advanced button */
4813     advanced_bt = gtk_button_new_with_label("Wireless Settings...");
4814     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_ADVANCED_KEY,advanced_bt);
4815
4816     SIGNAL_CONNECT(advanced_bt, "clicked", toolbar_display_airpcap_advanced_cb, airpcap_tb);
4817     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), advanced_bt,
4818         "Set Advanced Wireless Settings", "Private");
4819
4820
4821     gtk_widget_show(advanced_bt);
4822 #endif /* GTK_MAJOR_VERSION */
4823
4824     /* Key Management button */
4825     key_management_bt = gtk_button_new_with_label("Decryption Keys...");
4826     OBJECT_SET_DATA(airpcap_tb,AIRPCAP_TOOLBAR_KEY_MANAGEMENT_KEY,key_management_bt);
4827
4828     SIGNAL_CONNECT(key_management_bt, "clicked", toolbar_display_airpcap_key_management_cb, airpcap_tb);
4829     gtk_toolbar_append_widget(GTK_TOOLBAR(airpcap_tb), key_management_bt,
4830                               "Manage Decryption Keys", "Private");
4831     gtk_widget_show(key_management_bt);
4832
4833     /* If no airpcap interface is present, gray everything */
4834     if(airpcap_if_active == NULL) {
4835         if(airpcap_if_list == NULL || g_list_length(airpcap_if_list) == 0) {
4836             /*No airpcap device found */
4837             airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
4838             /* recent.airpcap_toolbar_show = TRUE; */
4839         } else {
4840             /* default adapter is not airpcap... or is airpcap but is not found*/
4841             airpcap_set_toolbar_stop_capture(airpcap_if_active);
4842             airpcap_enable_toolbar_widgets(airpcap_tb,FALSE);
4843             /* recent.airpcap_toolbar_show = TRUE; */
4844         }
4845     } else {
4846         airpcap_set_toolbar_stop_capture(airpcap_if_active);
4847         /* recent.airpcap_toolbar_show = TRUE; */
4848     }
4849 #endif
4850
4851     /* filter toolbar */
4852 #if GTK_MAJOR_VERSION < 2
4853     filter_tb = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL,
4854                                GTK_TOOLBAR_BOTH);
4855 #else
4856     filter_tb = gtk_toolbar_new();
4857     gtk_toolbar_set_orientation(GTK_TOOLBAR(filter_tb),
4858                                 GTK_ORIENTATION_HORIZONTAL);
4859 #endif /* GTK_MAJOR_VERSION */
4860     gtk_widget_show(filter_tb);
4861
4862     /* Create the "Filter:" button */
4863     filter_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
4864     SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
4865     gtk_widget_show(filter_bt);
4866     OBJECT_SET_DATA(top_level, E_FILT_BT_PTR_KEY, filter_bt);
4867
4868     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_bt,
4869         "Open the \"Display Filter\" dialog, to edit/apply filters", "Private");
4870
4871     /* Create the filter combobox */
4872     filter_cm = gtk_combo_new();
4873     dfilter_list = NULL;
4874     gtk_combo_disable_activate(GTK_COMBO(filter_cm));
4875     gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
4876     OBJECT_SET_DATA(filter_cm, E_DFILTER_FL_KEY, dfilter_list);
4877     filter_te = GTK_COMBO(filter_cm)->entry;
4878     main_display_filter_widget=filter_te;
4879     OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
4880     OBJECT_SET_DATA(filter_te, E_DFILTER_CM_KEY, filter_cm);
4881     OBJECT_SET_DATA(top_level, E_DFILTER_CM_KEY, filter_cm);
4882     SIGNAL_CONNECT(filter_te, "activate", filter_activate_cb, filter_te);
4883     SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
4884     WIDGET_SET_SIZE(filter_cm, 400, -1);
4885     gtk_widget_show(filter_cm);
4886     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_cm,
4887         NULL, NULL);
4888     /* setting a tooltip for a combobox will do nothing, so add it to the corresponding text entry */
4889     gtk_tooltips_set_tip(tooltips, filter_te,
4890         "Enter a display filter, or choose one of your recently used filters. "
4891         "The background color of this field is changed by a continuous syntax check (green is valid, red is invalid, yellow may have unexpected results).",
4892         NULL);
4893
4894     /* Create the "Add Expression..." button, to pop up a dialog
4895        for constructing filter comparison expressions. */
4896     filter_add_expr_bt = BUTTON_NEW_FROM_STOCK(WIRESHARK_STOCK_ADD_EXPRESSION);
4897     OBJECT_SET_DATA(filter_tb, E_FILT_FILTER_TE_KEY, filter_te);
4898     SIGNAL_CONNECT(filter_add_expr_bt, "clicked", filter_add_expr_bt_cb, filter_tb);
4899     gtk_widget_show(filter_add_expr_bt);
4900     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_add_expr_bt,
4901         "Add an expression to this filter string", "Private");
4902
4903     /* Create the "Clear" button */
4904     filter_reset = BUTTON_NEW_FROM_STOCK(GTK_STOCK_CLEAR);
4905     OBJECT_SET_DATA(filter_reset, E_DFILTER_TE_KEY, filter_te);
4906     SIGNAL_CONNECT(filter_reset, "clicked", filter_reset_cb, NULL);
4907     gtk_widget_show(filter_reset);
4908     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_reset,
4909         "Clear this filter string and update the display", "Private");
4910
4911     /* Create the "Apply" button */
4912     filter_apply = BUTTON_NEW_FROM_STOCK(GTK_STOCK_APPLY);
4913     OBJECT_SET_DATA(filter_apply, E_DFILTER_CM_KEY, filter_cm);
4914     SIGNAL_CONNECT(filter_apply, "clicked", filter_activate_cb, filter_te);
4915     gtk_widget_show(filter_apply);
4916     gtk_toolbar_append_widget(GTK_TOOLBAR(filter_tb), filter_apply,
4917         "Apply this filter string to the display", "Private");
4918
4919     /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
4920      * of any widget that ends up calling a callback which needs
4921      * that text entry pointer */
4922     set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
4923     set_menu_object_data("/Edit/Copy/As Filter", E_DFILTER_TE_KEY,
4924                          filter_te);
4925     set_menu_object_data("/Analyze/Display Filters...", E_FILT_TE_PTR_KEY,
4926                          filter_te);
4927     set_menu_object_data("/Analyze/Follow TCP Stream", E_DFILTER_TE_KEY,
4928                          filter_te);
4929     set_menu_object_data("/Analyze/Follow UDP Stream", E_DFILTER_TE_KEY,
4930                          filter_te);
4931     set_menu_object_data("/Analyze/Follow SSL Stream", E_DFILTER_TE_KEY,
4932                          filter_te);
4933     set_menu_object_data("/Analyze/Apply as Filter/Selected", E_DFILTER_TE_KEY,
4934                          filter_te);
4935     set_menu_object_data("/Analyze/Apply as Filter/Not Selected", E_DFILTER_TE_KEY,
4936                          filter_te);
4937     set_menu_object_data("/Analyze/Apply as Filter/... and Selected", E_DFILTER_TE_KEY,
4938                          filter_te);
4939     set_menu_object_data("/Analyze/Apply as Filter/... or Selected", E_DFILTER_TE_KEY,
4940                          filter_te);
4941     set_menu_object_data("/Analyze/Apply as Filter/... and not Selected", E_DFILTER_TE_KEY,
4942                          filter_te);
4943     set_menu_object_data("/Analyze/Apply as Filter/... or not Selected", E_DFILTER_TE_KEY,
4944                          filter_te);
4945     set_menu_object_data("/Analyze/Prepare a Filter/Selected", E_DFILTER_TE_KEY,
4946                          filter_te);
4947     set_menu_object_data("/Analyze/Prepare a Filter/Not Selected", E_DFILTER_TE_KEY,
4948                          filter_te);
4949     set_menu_object_data("/Analyze/Prepare a Filter/... and Selected", E_DFILTER_TE_KEY,
4950                          filter_te);
4951     set_menu_object_data("/Analyze/Prepare a Filter/... or Selected", E_DFILTER_TE_KEY,
4952                          filter_te);
4953     set_menu_object_data("/Analyze/Prepare a Filter/... and not Selected", E_DFILTER_TE_KEY,
4954                          filter_te);
4955     set_menu_object_data("/Analyze/Prepare a Filter/... or not Selected", E_DFILTER_TE_KEY,
4956                          filter_te);
4957     set_menu_object_data("/Conversation Filter/Ethernet", E_DFILTER_TE_KEY,
4958                          filter_te);
4959     set_menu_object_data("/Conversation Filter/IP", E_DFILTER_TE_KEY,
4960                          filter_te);
4961     set_menu_object_data("/Conversation Filter/TCP", E_DFILTER_TE_KEY,
4962                          filter_te);
4963     set_menu_object_data("/Conversation Filter/UDP", E_DFILTER_TE_KEY,
4964                          filter_te);
4965     set_menu_object_data("/Conversation Filter/PN-CBA Server", E_DFILTER_TE_KEY,
4966                          filter_te);
4967     set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
4968     OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
4969     OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_KEY, packet_list);
4970
4971     /* info (main) statusbar */
4972     info_bar = info_bar_new();
4973     gtk_widget_show(info_bar);
4974
4975     /* packets statusbar */
4976     packets_bar = packets_bar_new();
4977     gtk_widget_show(packets_bar);
4978
4979     /* profile statusbar */
4980     profile_bar = profile_bar_new();
4981     gtk_widget_show(profile_bar);
4982
4983     /* Filter/status hbox */
4984     stat_hbox = gtk_hbox_new(FALSE, 1);
4985     gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
4986     gtk_widget_show(stat_hbox);
4987
4988     /* Pane for the statusbar */
4989     status_pane_left = gtk_hpaned_new();
4990     gtk_widget_show(status_pane_left);
4991     status_pane_right = gtk_hpaned_new();
4992     gtk_widget_show(status_pane_right);
4993
4994     /* Pane for the welcome screen */
4995     welcome_pane = welcome_new();
4996     gtk_widget_show(welcome_pane);
4997 }
4998
4999 #ifdef HAVE_AIRPCAP
5000 static void
5001 driver_warning_dialog_cb(gpointer dialog, gint btn _U_, gpointer data _U_)
5002 {
5003     gboolean r;
5004
5005     r = simple_dialog_check_get(dialog);
5006     recent.airpcap_driver_check_show = !r;
5007 }
5008 #endif
5009
5010 static void
5011 show_main_window(gboolean doing_work)
5012 {
5013   main_set_for_capture_file(doing_work);
5014
5015   /*** we have finished all init things, show the main window ***/
5016   gtk_widget_show(top_level);
5017
5018   /* the window can be maximized only, if it's visible, so do it after show! */
5019   main_load_window_geometry(top_level);
5020
5021   /* process all pending GUI events before continue */
5022   while (gtk_events_pending()) gtk_main_iteration();
5023
5024   /* Pop up any queued-up alert boxes. */
5025   display_queued_messages();
5026
5027   /* Move the main window to the front, in case it isn't already there */
5028   gdk_window_raise(top_level->window);
5029
5030 #ifdef HAVE_AIRPCAP
5031   /*
5032    * This will read the decryption keys from the preferences file, and will
5033    * store them into the registry...
5034    */
5035   if(airpcap_if_list != NULL && g_list_length(airpcap_if_list) > 0){
5036     if (!airpcap_check_decryption_keys(airpcap_if_list)) {
5037       /* Ask the user what to do ...*/
5038       airpcap_keys_check_w(NULL,NULL);
5039     } else {
5040       /* Keys from lists are equals, or wireshark has got no keys */
5041       airpcap_load_decryption_keys(airpcap_if_list);
5042     }
5043   }
5044
5045   switch (airpcap_dll_ret_val) {
5046
5047   case AIRPCAP_DLL_OK:
5048     break;
5049
5050   case AIRPCAP_DLL_OLD:
5051     if(recent.airpcap_driver_check_show) {
5052       driver_warning_dialog = simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s",
5053                         "WARNING: The version of AirPcap on this system\n"
5054                         "does not support driver-level decryption.  Please\n"
5055                         "download a more recent version from\n" "http://www.cacetech.com/support/downloads.htm \n");
5056       simple_dialog_check_set(driver_warning_dialog,"Don't show this message again.");
5057       simple_dialog_set_cb(driver_warning_dialog, driver_warning_dialog_cb, NULL);
5058     }
5059     break;
5060
5061 #if 0
5062   /*
5063    * XXX - Maybe we need to warn the user if one of the following happens???
5064    */
5065   case AIRPCAP_DLL_ERROR:
5066     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DLL_ERROR\n");
5067     break;
5068
5069   case AIRPCAP_DLL_NOT_FOUND:
5070     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "%s","AIRPCAP_DDL_NOT_FOUND\n");
5071     break;
5072 #endif
5073   }
5074 #endif /* HAVE_AIRPCAP */
5075 }
5076
5077 /* Fill in capture options with values from the preferences */
5078 void
5079 prefs_to_capture_opts(void)
5080 {
5081 #ifdef HAVE_LIBPCAP
5082   /* Set promiscuous mode from the preferences setting. */
5083   /* the same applies to other preferences settings as well. */
5084     capture_opts->promisc_mode   = prefs.capture_prom_mode;
5085     capture_opts->show_info      = prefs.capture_show_info;
5086     capture_opts->real_time_mode = prefs.capture_real_time;
5087     auto_scroll_live             = prefs.capture_auto_scroll;
5088 #endif /* HAVE_LIBPCAP */
5089
5090   /* Set the name resolution code's flags from the preferences. */
5091     g_resolv_flags = prefs.name_resolve;
5092 }
5093
5094
5095 /* Change configuration profile */
5096 void change_configuration_profile (const gchar *profile_name)
5097 {
5098    char  *gdp_path, *dp_path;
5099
5100    /* First check if profile exists */
5101    if (!profile_exists(profile_name)) {
5102      return;
5103    }
5104
5105    /* Set profile name and update the status bar */
5106    set_profile_name (profile_name);
5107    profile_bar_update ();
5108
5109    /* Reset current preferences and apply the new */
5110    prefs_reset();
5111    (void) read_configuration_files (&gdp_path, &dp_path);
5112    prefs_apply_all();
5113
5114    /* Update window view and redraw the toolbar */
5115    update_main_window_name();
5116    toolbar_redraw_all();
5117
5118    /* Enable all protocols and disable from the disabled list */
5119    proto_enable_all();
5120    if (gdp_path == NULL && dp_path == NULL) {
5121      set_disabled_protos_list();
5122    }
5123
5124    /* Reload color filters */
5125    color_filters_reload();
5126
5127    /* Recreate the packet list according to new preferences */
5128    packet_list_recreate ();
5129    user_font_apply();
5130 }