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