/* main.c
*
- * $Id: main.c,v 1.436 2004/05/20 12:01:12 ulfl Exp $
+ * $Id$
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- * To do:
- * - Graphs
- * - Playback window
- * - Multiple window support
- * - Add cut/copy/paste
- * - Create header parsing routines
- * - Make byte view selections more fancy?
*/
#ifdef HAVE_CONFIG_H
#include "getopt.h"
#endif
-#ifdef WIN32 /* Needed for console I/O */
+#ifdef _WIN32 /* Needed for console I/O */
#include <fcntl.h>
#include <conio.h>
#endif
#include <epan/plugins.h>
#include <epan/dfilter/dfilter.h>
#include <epan/strutil.h>
-#include <epan/resolv.h>
+#include <epan/addr_resolv.h>
/* general (not GTK specific) */
-#include "cvsversion.h"
+#include "svnversion.h"
#include "file.h"
#include "summary.h"
#include "filters.h"
#include "disabled_protos.h"
-#include "prefs.h"
-#include "filter_prefs.h"
+#include <epan/prefs.h>
+#include "filter_dlg.h"
#include "layout_prefs.h"
#include "color.h"
#include "color_filters.h"
-#include "color_utils.h"
#include "print.h"
#include "simple_dialog.h"
#include "register.h"
-#include "prefs-int.h"
+#include <epan/prefs-int.h>
#include "ringbuffer.h"
#include "../ui_util.h" /* beware: ui_util.h exists twice! */
-#include "tap.h"
+#include <epan/tap.h>
#include "util.h"
+#include "clopts_common.h"
#include "version_info.h"
#include "capture.h"
+#include "merge.h"
#ifdef HAVE_LIBPCAP
#include "pcap-util.h"
#endif
-#ifdef WIN32
+#ifdef _WIN32
#include "capture-wpcap.h"
#endif
+#if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
+#include "ethclist.h"
+#endif
/* GTK related */
#include "statusbar.h"
#include "main.h"
#include "menu.h"
+#include "../main_window.h"
#include "../menu.h"
#include "file_dlg.h"
-#include "column.h"
+#include <epan/column.h>
#include "proto_draw.h"
#include "keys.h"
#include "packet_win.h"
#include "packet_list.h"
#include "recent.h"
#include "follow_dlg.h"
+#include "font_utils.h"
+#include "about_dlg.h"
+#include "help_dlg.h"
+#include "decode_as_dlg.h"
+#include "webbrowser.h"
+#include "capture_dlg.h"
+#if 0
+#include "../image/eicon3d64.xpm"
+#endif
+#include "capture_ui_utils.h"
+
+
+
+/*
+ * File under personal preferences directory in which GTK settings for
+ * Ethereal are stored.
+ */
+#define RC_FILE "gtkrc"
+#ifdef HAVE_LIBPCAP
+#define DEF_READY_MESSAGE " Ready to load or capture"
+#else
+#define DEF_READY_MESSAGE " Ready to load file"
+#endif
capture_file cfile;
GtkWidget *main_display_filter_widget=NULL;
GtkWidget *top_level = NULL, *tree_view, *byte_nb_ptr, *tv_scrollw;
-static GtkWidget *none_lb, *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
+static GtkWidget *main_pane_v1, *main_pane_v2, *main_pane_h1, *main_pane_h2;
static GtkWidget *main_first_pane, *main_second_pane;
static GtkWidget *status_pane;
static GtkWidget *menubar, *main_vbox, *main_tb, *pkt_scrollw, *stat_hbox, *filter_tb;
static GtkWidget *info_bar;
static GtkWidget *packets_bar = NULL;
-#if GTK_MAJOR_VERSION < 2
-GdkFont *m_r_font, *m_b_font;
-guint m_font_height, m_font_width;
-#else
-PangoFontDescription *m_r_font, *m_b_font;
-#endif
+static GtkWidget *welcome_pane;
static guint main_ctx, file_ctx, help_ctx;
static guint packets_ctx;
static gchar *packets_str = NULL;
GString *comp_info_str, *runtime_info_str;
gchar *ethereal_path = NULL;
-gchar *last_open_dir = NULL;
-static gboolean updated_last_open_dir = FALSE;
+gboolean have_capture_file = FALSE; /* XXX - is there an aquivalent in cfile? */
-#if GTK_MAJOR_VERSION < 2
-GtkStyle *item_style;
-#endif
-
-#ifdef WIN32
+#ifdef _WIN32
static gboolean has_console; /* TRUE if app has console */
/*static void create_console(void);*/
static void destroy_console(void);
#ifdef HAVE_LIBPCAP
static gboolean list_link_layer_types;
+capture_options global_capture_opts;
+capture_options *capture_opts = &global_capture_opts;
#endif
+
static void create_main_window(gint, gint, gint, e_prefs*);
-static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_);
+static void show_main_window(gboolean);
+static void file_quit_answered_cb(gpointer dialog, gint btn, gpointer data);
static void main_save_window_geometry(GtkWidget *widget);
-#ifdef WIN32
-#if GTK_MAJOR_VERSION >= 2
-static void try_to_get_windows_font_gtk2 (void);
-#endif
-#endif
#define E_DFILTER_CM_KEY "display_filter_combo"
#define E_DFILTER_FL_KEY "display_filter_list"
-#if GTK_MAJOR_VERSION < 2
-void
-set_fonts(GdkFont *regular, GdkFont *bold)
-#else
-void
-set_fonts(PangoFontDescription *regular, PangoFontDescription *bold)
-#endif
-{
- /* Yes, assert. The code that loads the font should check
- * for NULL and provide its own error message. */
- g_assert(m_r_font && m_b_font);
- m_r_font = regular;
- m_b_font = bold;
-
-#if GTK_MAJOR_VERSION < 2
- m_font_height = m_r_font->ascent + m_r_font->descent;
- m_font_width = gdk_string_width(m_r_font, "0");
-#endif
-}
-
-/*
- * Go to frame specified by currently selected protocol tree item.
- */
-void
-goto_framenum_cb(GtkWidget *w _U_, gpointer data _U_)
-{
- if (cfile.finfo_selected) {
- header_field_info *hfinfo;
- guint32 framenum;
-
- hfinfo = cfile.finfo_selected->hfinfo;
- g_assert(hfinfo);
- if (hfinfo->type == FT_FRAMENUM) {
- framenum = fvalue_get_integer(&cfile.finfo_selected->value);
- if (framenum != 0)
- goto_frame(&cfile, framenum);
- }
- }
-}
-
-void
-goto_top_frame_cb(GtkWidget *w _U_, gpointer d _U_)
-{
- goto_top_frame(&cfile);
-}
-
-void
-goto_bottom_frame_cb(GtkWidget *w _U_, gpointer d _U_)
-{
- goto_bottom_frame(&cfile);
-}
-
-
-void
-view_zoom_in_cb(GtkWidget *w _U_, gpointer d _U_)
-{
- gint save_gui_zoom_level;
-
- save_gui_zoom_level = recent.gui_zoom_level;
- recent.gui_zoom_level++;
- switch (font_apply()) {
-
- case FA_SUCCESS:
- break;
-
- case FA_FONT_NOT_RESIZEABLE:
- /* "font_apply()" popped up an alert box. */
- recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
- break;
-
- case FA_FONT_NOT_AVAILABLE:
- /* We assume this means that the specified size isn't available. */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Your current font isn't available in the next larger size.\n");
- recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
- break;
- }
-}
-
-void
-view_zoom_out_cb(GtkWidget *w _U_, gpointer d _U_)
-{
- gint save_gui_zoom_level;
-
- save_gui_zoom_level = recent.gui_zoom_level;
- recent.gui_zoom_level--;
- switch (font_apply()) {
-
- case FA_SUCCESS:
- break;
-
- case FA_FONT_NOT_RESIZEABLE:
- /* "font_apply()" popped up an alert box. */
- recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
- break;
-
- case FA_FONT_NOT_AVAILABLE:
- /* We assume this means that the specified size isn't available. */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Your current font isn't available in the next smaller size.\n");
- recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
- break;
- }
-}
-
-void
-view_zoom_100_cb(GtkWidget *w _U_, gpointer d _U_)
-{
- gint save_gui_zoom_level;
-
- save_gui_zoom_level = recent.gui_zoom_level;
- recent.gui_zoom_level = 0;
- switch (font_apply()) {
-
- case FA_SUCCESS:
- break;
-
- case FA_FONT_NOT_RESIZEABLE:
- /* "font_apply()" popped up an alert box. */
- recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
- break;
-
- case FA_FONT_NOT_AVAILABLE:
- /* We assume this means that the specified size isn't available.
- XXX - this "shouldn't happen". */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Your current font couldn't be reloaded at the size you selected.\n");
- recent.gui_zoom_level = save_gui_zoom_level; /* undo zoom */
- break;
- }
-}
-
-
/* Match selected byte pattern */
static void
match_selected_cb_do(gpointer data, int action, gchar *text)
}
void
-match_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
+match_selected_ptree_cb(GtkWidget *w, gpointer data, MATCH_SELECTED_E action)
{
if (cfile.finfo_selected)
match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
+ action,
proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
}
-void
-match_selected_cb_and_ptree(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
-void
-match_selected_cb_or_ptree(GtkWidget *w, gpointer data)
+static void selected_ptree_info_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
+ gchar *selected_proto_url;
+ gchar *proto_abbrev = data;
-void
-match_selected_cb_not_ptree(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
-void
-match_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
+ switch(btn) {
+ case(ESD_BTN_OK):
+ if (cfile.finfo_selected) {
+ /* open wiki page using the protocol abbreviation */
+ selected_proto_url = g_strdup_printf("http://wiki.ethereal.com/Protocols/%s", proto_abbrev);
+ browser_open_url(selected_proto_url);
+ g_free(selected_proto_url);
+ }
+ break;
+ case(ESD_BTN_CANCEL):
+ break;
+ default:
+ g_assert_not_reached();
+ }
}
-void
-match_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR_NOT,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
-void
-prepare_selected_cb_replace_ptree(GtkWidget *w, gpointer data)
+void
+selected_ptree_info_cb(GtkWidget *widget _U_, gpointer data _U_)
{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_REPLACE,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
+ int field_id;
+ gchar *proto_abbrev;
+ gpointer dialog;
-void
-prepare_selected_cb_and_ptree(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
-void
-prepare_selected_cb_or_ptree(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
+ if (cfile.finfo_selected) {
+ /* convert selected field to protocol abbreviation */
+ /* XXX - could this conversion be simplified? */
+ field_id = cfile.finfo_selected->hfinfo->id;
+ /* if the selected field isn't a protocol, get it's parent */
+ if(!proto_registrar_is_protocol(field_id)) {
+ field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
+ }
-void
-prepare_selected_cb_not_ptree(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_NOT,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
+ proto_abbrev = proto_registrar_get_abbrev(field_id);
+
+ /* ask the user if the wiki page really should be opened */
+ dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
+ PRIMARY_TEXT_START "Open Ethereal Wiki page of protocol \"%s\"?" PRIMARY_TEXT_END "\n"
+ "\n"
+ "This will open the \"%s\" related Ethereal Wiki page in your Web browser.\n"
+ "\n"
+ "The Ethereal Wiki is a collaborative approach to provide information\n"
+ "about Ethereal in several ways (not limited to protocol specifics).\n"
+ "\n"
+ "This Wiki is new, so the page of the selected protocol\n"
+ "may not exist and/or may not contain valuable information.\n"
+ "\n"
+ "As everyone can edit the Wiki and add new content (or extend existing),\n"
+ "you are encouraged to add information if you can.\n"
+ "\n"
+ "Hint 1: If you are new to wiki editing, try out editing the Sandbox first!\n"
+ "\n"
+ "Hint 2: If you want to add a new protocol page, you should use the ProtocolTemplate,\n"
+ "which will save you a lot of editing and will give a consistent look over the pages.",
+ proto_abbrev, proto_abbrev);
+ simple_dialog_set_cb(dialog, selected_ptree_info_answered_cb, proto_abbrev);
+ }
}
-void
-prepare_selected_cb_and_ptree_not(GtkWidget *w, gpointer data)
-{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_AND_NOT,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
-}
-void
-prepare_selected_cb_or_ptree_not(GtkWidget *w, gpointer data)
+void
+selected_ptree_ref_cb(GtkWidget *widget _U_, gpointer data _U_)
{
- if (cfile.finfo_selected)
- match_selected_cb_do((data ? data : w),
- MATCH_SELECTED_OR_NOT,
- proto_construct_dfilter_string(cfile.finfo_selected, cfile.edt));
+ int field_id;
+ gchar *proto_abbrev;
+ gchar *selected_proto_url;
+
+
+ if (cfile.finfo_selected) {
+ /* convert selected field to protocol abbreviation */
+ /* XXX - could this conversion be simplified? */
+ field_id = cfile.finfo_selected->hfinfo->id;
+ /* if the selected field isn't a protocol, get it's parent */
+ if(!proto_registrar_is_protocol(field_id)) {
+ field_id = proto_registrar_get_parent(cfile.finfo_selected->hfinfo->id);
+ }
+
+ proto_abbrev = proto_registrar_get_abbrev(field_id);
+
+ /* open reference page using the protocol abbreviation */
+ selected_proto_url = g_strdup_printf("http://www.ethereal.com/docs/dfref/%c/%s", proto_abbrev[0], proto_abbrev);
+ browser_open_url(selected_proto_url);
+ g_free(selected_proto_url);
+ }
}
+
static gchar *
get_text_from_packet_list(gpointer data)
{
}
void
-match_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
-void
-match_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_replace_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_REPLACE,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_and_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_AND,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_or_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_not_plist(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_NOT,
- get_text_from_packet_list(data));
-}
-
-void
-prepare_selected_cb_and_plist_not(GtkWidget *w _U_, gpointer data)
+match_selected_plist_cb(GtkWidget *w _U_, gpointer data, MATCH_SELECTED_E action)
{
match_selected_cb_do(data,
- MATCH_SELECTED_AND_NOT,
+ action,
get_text_from_packet_list(data));
}
-void
-prepare_selected_cb_or_plist_not(GtkWidget *w _U_, gpointer data)
-{
- match_selected_cb_do(data,
- MATCH_SELECTED_OR_NOT,
- get_text_from_packet_list(data));
-}
/* XXX: use a preference for this setting! */
}
-/* call filter_packets() and add this filter string to the recent filter list */
+/* call cf_filter_packets() and add this filter string to the recent filter list */
gboolean
main_filter_packets(capture_file *cf, const gchar *dftext, gboolean force)
{
gboolean add_filter = TRUE;
gboolean free_filter = TRUE;
char *s;
- gboolean filter_packets_ret;
+ cf_status_t cf_status;
s = g_strdup(dftext);
/* GtkCombos don't let us get at their list contents easily, so we maintain
our own filter list, and feed it to gtk_combo_set_popdown_strings when
a new filter is added. */
- if ((filter_packets_ret = filter_packets(cf, s, force))) {
+ cf_status = cf_filter_packets(cf, s, force);
+ if (cf_status == CF_OK) {
li = g_list_first(filter_list);
while (li) {
if (li->data && strcmp(s, li->data) == 0)
if (free_filter)
g_free(s);
- return filter_packets_ret;
+ return (cf_status == CF_OK);
}
} else {
frame->flags.ref_time=0;
}
- reftime_packets(&cfile);
+ cf_reftime_packets(&cfile);
}
-/* 0: toggle ref time status for the selected frame
- * 1: find next ref time frame
- * 2: find previous reftime frame
- */
void
-reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, guint action)
+reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_, REFTIME_ACTION_E action)
{
switch(action){
- case 0: /* toggle ref frame */
+ case REFTIME_TOGGLE:
if (cfile.current_frame) {
/* XXX hum, should better have a "cfile->current_row" here ... */
set_frame_reftime(!cfile.current_frame->flags.ref_time,
packet_list_find_row_from_data(cfile.current_frame));
}
break;
- case 1: /* find next ref frame */
+ case REFTIME_FIND_NEXT:
find_previous_next_frame_with_filter("frame.ref_time", FALSE);
break;
- case 2: /* find previous ref frame */
+ case REFTIME_FIND_PREV:
find_previous_next_frame_with_filter("frame.ref_time", TRUE);
break;
}
if (byte_data == NULL)
return; /* none */
- unselect_field(&cfile);
+ cf_unselect_field(&cfile);
packet_hex_print(GTK_TEXT_VIEW(byte_view), byte_data,
cfile.current_frame, NULL, byte_len);
return;
if (data == NULL)
return; /* none */
- unselect_field(&cfile);
+ cf_unselect_field(&cfile);
packet_hex_print(GTK_TEXT(byte_view), data, cfile.current_frame,
NULL, len);
}
}
}
+void
+main_set_for_capture_file(gboolean have_capture_file_in)
+{
+ have_capture_file = have_capture_file_in;
+
+ main_widgets_show_or_hide();
+}
gboolean
main_do_quit(void)
#ifdef HAVE_LIBPCAP
/* Nuke any child capture in progress. */
- kill_capture_child();
+ capture_kill_child(capture_opts);
#endif
/* Are we in the middle of reading a capture? */
{
gpointer dialog;
- if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
+ if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
+#if GTK_MAJOR_VERSION >= 2
+ gtk_window_present(GTK_WINDOW(top_level));
+#endif
/* user didn't saved his current file, ask him */
- dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
+ dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
"If you quit the program without saving, your capture data will be discarded.");
simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
return TRUE;
} else {
/* unchanged file, just exit */
- /* "main_do_quit()" indicates whether the main window should be deleted. */
- return main_do_quit();
+ /* "main_do_quit()" indicates whether the main window should be deleted. */
+ return main_do_quit();
}
}
+
+
static void
-main_load_window_geometry(GtkWidget *widget
-#if GTK_MAJOR_VERSION < 2
- _U_
-#endif
-)
-{
- /* as we now have the geometry from the recent file, set it */
- if (prefs.gui_geometry_save_position) {
- gtk_widget_set_uposition(GTK_WIDGET(top_level),
- recent.gui_geometry_main_x,
- recent.gui_geometry_main_y);
- }
- if (prefs.gui_geometry_save_size) {
- WIDGET_SET_SIZE(top_level,
- recent.gui_geometry_main_width,
- recent.gui_geometry_main_height);
+main_load_window_geometry(GtkWidget *widget)
+{
+ window_geometry_t geom;
+
+ geom.set_pos = prefs.gui_geometry_save_position;
+ geom.x = recent.gui_geometry_main_x;
+ geom.y = recent.gui_geometry_main_y;
+ geom.set_size = prefs.gui_geometry_save_size;
+ if (recent.gui_geometry_main_width > 0 &&
+ recent.gui_geometry_main_height > 0) {
+ geom.width = recent.gui_geometry_main_width;
+ geom.height = recent.gui_geometry_main_height;
+ geom.set_maximized = prefs.gui_geometry_save_maximized;
} else {
- WIDGET_SET_SIZE(top_level, DEF_WIDTH, -1);
+ /* We assume this means the width and height weren't set in
+ the "recent" file (or that there is no "recent" file),
+ and weren't set to a default value, so we don't set the
+ size. (The "recent" file code rejects non-positive width
+ and height values.) */
+ geom.set_size = FALSE;
}
+ geom.maximized = recent.gui_geometry_main_maximized;
+
+ window_set_geometry(widget, &geom);
+
#if GTK_MAJOR_VERSION >= 2
- if(prefs.gui_geometry_save_maximized) {
- if (recent.gui_geometry_main_maximized) {
- gdk_window_maximize(widget->window);
- } else {
- gdk_window_unmaximize(widget->window);
- }
- }
-
/* XXX - rename recent settings? */
if (recent.gui_geometry_main_upper_pane)
gtk_paned_set_position(GTK_PANED(main_first_pane), recent.gui_geometry_main_upper_pane);
#endif
}
+
static void
main_save_window_geometry(GtkWidget *widget)
{
- gint desk_x, desk_y;
-#if GTK_MAJOR_VERSION >= 2
- GdkWindowState state;
-#endif
+ window_geometry_t geom;
- /* Try to grab our geometry.
-
- GTK+ provides two routines to get a window's position relative
- to the X root window. If I understand the documentation correctly,
- gdk_window_get_deskrelative_origin applies mainly to Enlightenment
- and gdk_window_get_root_origin applies for all other WMs.
-
- The code below tries both routines, and picks the one that returns
- the upper-left-most coordinates.
-
- More info at:
-
- http://mail.gnome.org/archives/gtk-devel-list/2001-March/msg00289.html
- http://www.gtk.org/faq/#AEN606
- */
+ window_get_geometry(widget, &geom);
if (prefs.gui_geometry_save_position) {
- gdk_window_get_root_origin(widget->window,
- &recent.gui_geometry_main_x,
- &recent.gui_geometry_main_y);
- if (gdk_window_get_deskrelative_origin(widget->window,
- &desk_x, &desk_y)) {
- if (desk_x <= recent.gui_geometry_main_x &&
- desk_y <= recent.gui_geometry_main_y)
- {
- recent.gui_geometry_main_x = desk_x;
- recent.gui_geometry_main_y = desk_y;
- }
- }
+ recent.gui_geometry_main_x = geom.x;
+ recent.gui_geometry_main_y = geom.y;
}
if (prefs.gui_geometry_save_size) {
- /* XXX - Is this the "approved" method? */
- gdk_window_get_size(widget->window,
- &recent.gui_geometry_main_width,
- &recent.gui_geometry_main_height);
+ recent.gui_geometry_main_width = geom.width,
+ recent.gui_geometry_main_height = geom.height;
}
#if GTK_MAJOR_VERSION >= 2
if(prefs.gui_geometry_save_maximized) {
- state = gdk_window_get_state(widget->window);
- recent.gui_geometry_main_maximized = (state == GDK_WINDOW_STATE_MAXIMIZED);
+ recent.gui_geometry_main_maximized = geom.maximized;
}
recent.gui_geometry_main_upper_pane = gtk_paned_get_position(GTK_PANED(main_first_pane));
static void file_quit_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
{
switch(btn) {
- case(ESD_BTN_YES):
+ case(ESD_BTN_SAVE):
/* save file first */
file_save_as_cmd(after_save_exit, NULL);
break;
- case(ESD_BTN_NO):
- main_do_quit();
+ case(ESD_BTN_DONT_SAVE):
+ main_do_quit();
break;
case(ESD_BTN_CANCEL):
break;
{
gpointer dialog;
- if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
+ if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
/* user didn't saved his current file, ask him */
- dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
+ dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
PRIMARY_TEXT_START "Save capture file before program quit?" PRIMARY_TEXT_END "\n\n"
"If you quit the program without saving, your capture data will be discarded.");
simple_dialog_set_cb(dialog, file_quit_answered_cb, NULL);
} else {
/* unchanged file, just exit */
- main_do_quit();
+ main_do_quit();
}
}
if (print_ver) {
output = stdout;
fprintf(output, "This is GNU " PACKAGE " " VERSION
-#ifdef CVSVERSION
- " (" CVSVERSION ")"
+#ifdef SVNVERSION
+ " (" SVNVERSION ")"
#endif
- "\n%s\n%s\n",
+ "\n%s\n\n%s\n",
comp_info_str->str, runtime_info_str->str);
} else {
output = stderr;
static void
show_version(void)
{
-#ifdef WIN32
+#ifdef _WIN32
create_console();
#endif
printf(PACKAGE " " VERSION
-#ifdef CVSVERSION
- " (" CVSVERSION ")"
+#ifdef SVNVERSION
+ " (" SVNVERSION ")"
#endif
- "\n%s\n%s\n",
+ "\n%s\n\n%s\n",
comp_info_str->str, runtime_info_str->str);
}
number = strtol(string, &p, 10);
if (p == string || *p != '\0') {
- fprintf(stderr, "ethereal: The specified %s \"%s\" is not a decimal number\n",
+ fprintf(stderr, "ethereal: The specified %s \"%s\" isn't a decimal number\n",
name, string);
exit(1);
}
return number;
}
-#ifdef HAVE_LIBPCAP
-/*
- * Given a string of the form "<autostop criterion>:<value>", as might appear
- * as an argument to a "-a" option, parse it and set the criterion in
- * question. Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-set_autostop_criterion(const char *autostoparg)
-{
- gchar *p, *colonp;
-
- colonp = strchr(autostoparg, ':');
- if (colonp == NULL)
- return FALSE;
-
- p = colonp;
- *p++ = '\0';
-
- /*
- * Skip over any white space (there probably won't be any, but
- * as we allow it in the preferences file, we might as well
- * allow it here).
- */
- while (isspace((guchar)*p))
- p++;
- if (*p == '\0') {
- /*
- * Put the colon back, so if our caller uses, in an
- * error message, the string they passed us, the message
- * looks correct.
- */
- *colonp = ':';
- return FALSE;
- }
- if (strcmp(autostoparg,"duration") == 0) {
- capture_opts.has_autostop_duration = TRUE;
- capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
- } else if (strcmp(autostoparg,"filesize") == 0) {
- capture_opts.has_autostop_filesize = TRUE;
- capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
- } else {
- return FALSE;
- }
- *colonp = ':'; /* put the colon back */
- return TRUE;
-}
-
-/*
- * Given a string of the form "<ring buffer file>:<duration>", as might appear
- * as an argument to a "-b" option, parse it and set the arguments in
- * question. Return an indication of whether it succeeded or failed
- * in some fashion.
- */
-static gboolean
-get_ring_arguments(const char *arg)
-{
- gchar *p = NULL, *colonp;
-
- colonp = strchr(arg, ':');
-
- if (colonp != NULL) {
- p = colonp;
- *p++ = '\0';
- }
-
- capture_opts.ring_num_files =
- get_natural_int(arg, "number of ring buffer files");
-
- if (colonp == NULL)
- return TRUE;
-
- /*
- * Skip over any white space (there probably won't be any, but
- * as we allow it in the preferences file, we might as well
- * allow it here).
- */
- while (isspace((guchar)*p))
- p++;
- if (*p == '\0') {
- /*
- * Put the colon back, so if our caller uses, in an
- * error message, the string they passed us, the message
- * looks correct.
- */
- *colonp = ':';
- return FALSE;
- }
-
- capture_opts.has_file_duration = TRUE;
- capture_opts.file_duration = get_positive_int(p,
- "ring buffer duration");
-
- *colonp = ':'; /* put the colon back */
- return TRUE;
-}
-#endif
-
-#if defined WIN32 || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
+#if defined(_WIN32) || GTK_MAJOR_VERSION < 2 || ! defined USE_THREADS
/*
Once every 3 seconds we get a callback here which we use to update
the tap extensions. Since Gtk1 is single threaded we dont have to
void
protect_thread_critical_region(void)
{
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
+#if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
g_static_mutex_lock(&update_thread_mutex);
#endif
}
void
unprotect_thread_critical_region(void)
{
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
+#if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined USE_THREADS
g_static_mutex_unlock(&update_thread_mutex);
#endif
}
}
+/* Set the file name in the status line, in the name for the main window,
+ and in the name for the main window's icon. */
+static void
+set_display_filename(capture_file *cf)
+{
+ const gchar *name_ptr;
+ size_t msg_len;
+ static const gchar done_fmt_nodrops[] = " File: %s %s %02u:%02u:%02u";
+ static const gchar done_fmt_drops[] = " File: %s %s %02u:%02u:%02u Drops: %u";
+ gchar *done_msg;
+ gchar *win_name_fmt = "%s - Ethereal";
+ gchar *win_name;
+ gchar *size_str;
+
+ name_ptr = cf_get_display_name(cf);
+
+ if (!cf->is_tempfile) {
+ /* Add this filename to the list of recent files in the "Recent Files" submenu */
+ add_menu_recent_capture_file(cf->filename);
+ }
-enum { DND_TARGET_STRING, DND_TARGET_ROOTWIN, DND_TARGET_URL };
+ if (cf->f_len/1024/1024 > 10) {
+ size_str = g_strdup_printf("%ld MB", cf->f_len/1024/1024);
+ } else if (cf->f_len/1024 > 10) {
+ size_str = g_strdup_printf("%ld KB", cf->f_len/1024);
+ } else {
+ size_str = g_strdup_printf("%ld bytes", cf->f_len);
+ }
-void
-dnd_open_file_cmd(gpointer cf_name)
+ if (cf->drops_known) {
+ done_msg = g_strdup_printf(done_fmt_drops, name_ptr, size_str,
+ cf->esec/3600, cf->esec%3600/60, cf->esec%60, cf->drops);
+ } else {
+ done_msg = g_strdup_printf(done_fmt_nodrops, name_ptr, size_str,
+ cf->esec/3600, cf->esec%3600/60, cf->esec%60);
+ }
+ statusbar_push_file_msg(done_msg);
+ g_free(done_msg);
+
+ msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
+ win_name = g_malloc(msg_len);
+ snprintf(win_name, msg_len, win_name_fmt, name_ptr);
+ set_main_window_name(win_name);
+ g_free(win_name);
+}
+
+
+static void
+main_cf_cb_file_closed(capture_file *cf)
{
- int err;
+ /* Destroy all windows, which refer to the
+ capture file we're closing. */
+ destroy_cfile_wins();
-
- /* open and read the capture file (this will close an existing file) */
- if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
- cf_read(&cfile);
- add_menu_recent_capture_file(cf_name);
- } else {
- /* the capture file couldn't be read (doesn't exist, file format unknown, ...) */
- }
+ /* Clear any file-related status bar messages.
+ XXX - should be "clear *ALL* file-related status bar messages;
+ will there ever be more than one on the stack? */
+ statusbar_pop_file_msg();
- g_free(cf_name);
+ /* Restore the standard title bar message. */
+ set_main_window_name("The Ethereal Network Analyzer");
+
+ /* Disable all menu items that make sense only if you have a capture. */
+ set_menus_for_capture_file(FALSE);
+ set_menus_for_unsaved_capture_file(FALSE);
+ set_menus_for_captured_packets(FALSE);
+ set_menus_for_selected_packet(cf);
+ set_menus_for_capture_in_progress(FALSE);
+ set_menus_for_selected_tree_row(cf);
+
+ /* Set up main window for no capture file. */
+ main_set_for_capture_file(FALSE);
}
-static void
-dnd_open_file_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
+static void
+main_cf_cb_file_read_start(capture_file *cf)
{
- switch(btn) {
- case(ESD_BTN_YES):
- /* save file first */
- file_save_as_cmd(after_save_open_dnd_file, data);
- break;
- case(ESD_BTN_NO):
- cf_close(&cfile);
- dnd_open_file_cmd(data);
- break;
- case(ESD_BTN_CANCEL):
- g_free(data);
- break;
- default:
- g_assert_not_reached();
- }
+ const gchar *name_ptr;
+ gchar *load_msg;
+
+ name_ptr = get_basename(cf->filename);
+
+ load_msg = g_strdup_printf(" Loading: %s", name_ptr);
+ statusbar_push_file_msg(load_msg);
+ g_free(load_msg);
}
-static gchar *
-dnd_uri2filename(gchar *cf_name)
+static void
+main_cf_cb_file_read_finished(capture_file *cf)
{
- gchar *src, *dest;
- gint ret;
- guint i;
- gchar esc[3];
+ statusbar_pop_file_msg();
+ set_display_filename(cf);
+ /* Enable menu items that make sense if you have a capture file you've
+ finished reading. */
+ set_menus_for_capture_file(TRUE);
+ set_menus_for_unsaved_capture_file(!cf->user_saved);
- /*
- * Remove URI header.
- * On win32 (at least WinXP), this string looks like (UNC or local filename):
- * file:////servername/sharename/dir1/dir2/capture-file.cap
- * or
- * file:///d:/dir1/dir2/capture-file.cap
- * we have to remove the prefix to get a valid filename.
- *
- * On UNIX (at least KDE 3.0 Konqueror), this string looks like:
- * file:/dir1/dir2/capture-file.cap
- * we have to remove the file: to get a valid filename.
- */
- if (strncmp("file:////", cf_name, 9) == 0) {
- /* now becoming: //servername/sharename/dir1/dir2/capture-file.cap */
- cf_name += 7;
- } else if (strncmp("file:///", cf_name, 8) == 0) {
- /* now becoming: d:/dir1/dir2/capture-file.cap */
- cf_name += 8;
- } else if (strncmp("file:", cf_name, 5) == 0) {
- /* now becoming: /dir1/dir2/capture-file.cap */
- cf_name += 5;
- }
+ /* Enable menu items that make sense if you have some captured packets. */
+ set_menus_for_captured_packets(TRUE);
- /*
- * unescape the escaped URI characters (spaces, ...)
- *
- * we have to replace escaped chars to their equivalents,
- * e.g. %20 (always a two digit hexstring) -> ' '
- * the percent character '%' is escaped be a double one "%%"
- *
- * we do this conversation "in place" as the result is always
- * equal or smaller in size.
- */
- src = cf_name;
- dest = cf_name;
- while (*src) {
- if (*src == '%') {
- src++;
- if (*src == '%') {
- /* this is an escaped '%' char (was: "%%") */
- *dest = *src;
- src++;
- dest++;
- } else {
- /* convert escaped hexnumber to unscaped character */
- esc[0] = src[0];
- esc[1] = src[1];
- esc[2] = '\0';
- ret = sscanf(esc, "%x", &i);
- if (ret == 1) {
- src+=2;
- *dest = (gchar) i;
- dest++;
- } else {
- /* somethings wrong, just jump over that char
- * this will result in a wrong string, but we might get
- * user feedback and can fix it later ;-) */
- src++;
- }
- }
- } else {
- *dest = *src;
- src++;
- dest++;
- }
- }
- *dest = '\0';
+ /* Set up main window for a capture file. */
+ main_set_for_capture_file(TRUE);
+}
- return cf_name;
+#ifdef HAVE_LIBPCAP
+static void
+main_cf_cb_live_capture_prepare(capture_options *capture_opts)
+{
+ gchar *title;
+
+
+ title = g_strdup_printf("%s: Capturing - Ethereal",
+ get_interface_descriptive_name(capture_opts->iface));
+ set_main_window_name(title);
+ g_free(title);
}
-static void
-dnd_data_received(GtkWidget *widget _U_, GdkDragContext *dc _U_, gint x _U_, gint y _U_,
-GtkSelectionData *selection_data, guint info, guint t _U_, gpointer data _U_)
+static void
+main_cf_cb_live_capture_started(capture_options *capture_opts)
{
- gchar *cf_name, *cf_name_ori;
- gpointer dialog;
+ gchar *capture_msg;
- if (info == DND_TARGET_URL) {
- /* DND_TARGET_URL on Win32:
- * The selection_data->data is a single string, containing one or more URI's,
- * seperated by CR/NL chars. The length of the whole field can be found
- * in the selection_data->length field. As we can't handle more than one
- * capture file at a time, we only try to load the first one. */
+ /* Disable menu items that make no sense if you're currently running
+ a capture. */
+ set_menus_for_capture_in_progress(TRUE);
- /* XXX: how does this string look like on other platforms? */
+ /* Enable menu items that make sense if you have some captured
+ packets (yes, I know, we don't have any *yet*). */
+ set_menus_for_captured_packets(TRUE);
- /* XXX: if more than one file is in the string, we might want to have
- * a dialog box asking to merge these files together? */
+ capture_msg = g_strdup_printf(" %s: <live capture in progress>", get_interface_descriptive_name(capture_opts->iface));
- /* the name might not be zero terminated -> make a copy of it */
- cf_name_ori = g_strndup((gchar *)selection_data->data, selection_data->length);
- cf_name = cf_name_ori;
+ statusbar_push_file_msg(capture_msg);
- /* replace trailing CR NL simply with zeroes */
- g_strdelimit(cf_name, "\r\n", '\0');
+ g_free(capture_msg);
- /* convert the URI to a local filename */
- cf_name = dnd_uri2filename(cf_name);
+ /* Set up main window for a capture file. */
+ main_set_for_capture_file(TRUE);
+}
- /* we need a clean name for later call to g_free() */
- cf_name = strdup(cf_name);
- g_free(cf_name_ori);
+static void
+main_cf_cb_live_capture_finished(capture_file *cf)
+{
+ /* Pop the "<live capture in progress>" message off the status bar. */
+ statusbar_pop_file_msg();
- /* ask the user to save it's current capture file first */
- if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
- /* user didn't saved his current file, ask him */
- dialog = simple_dialog(ESD_TYPE_CONFIRMATION,
- ESD_BTNS_YES_NO_CANCEL,
- PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
- "If you open a new capture file without saving, your current capture data will be discarded.");
- simple_dialog_set_cb(dialog, dnd_open_file_answered_cb, cf_name);
- } else {
- /* unchanged file */
- dnd_open_file_cmd(cf_name);
- }
- }
+ set_display_filename(cf);
+
+ /* Enable menu items that make sense if you're not currently running
+ a capture. */
+ set_menus_for_capture_in_progress(FALSE);
+
+ /* Enable menu items that make sense if you have a capture file
+ you've finished reading. */
+ set_menus_for_capture_file(TRUE);
+ set_menus_for_unsaved_capture_file(!cf->user_saved);
+
+ /* Set up main window for a capture file. */
+ main_set_for_capture_file(TRUE);
}
+#endif
-static void
-dnd_init(GtkWidget *w)
+static void
+main_cf_cb_packet_selected(gpointer data)
{
- /* we are only interested in the URI list containing filenames */
- static GtkTargetEntry target_entry[] = {
- /*{"STRING", 0, DND_TARGET_STRING},*/
- /*{"text/plain", 0, DND_TARGET_STRING},*/
- {"text/uri-list", 0, DND_TARGET_URL}
- };
+ capture_file *cf = data;
- /* set this window as a dnd destination */
- gtk_drag_dest_set(
- w, GTK_DEST_DEFAULT_ALL, target_entry,
- sizeof(target_entry) / sizeof(GtkTargetEntry),
- (GdkDragAction)(GDK_ACTION_MOVE | GDK_ACTION_COPY) );
+ /* Display the GUI protocol tree and hex dump.
+ XXX - why do we dump core if we call "proto_tree_draw()"
+ before calling "add_byte_views()"? */
+ add_main_byte_views(cf->edt);
+ main_proto_tree_draw(cf->edt->tree);
- /* get notified, if some dnd coming in */
- gtk_signal_connect(GTK_OBJECT(w), "drag_data_received",
- GTK_SIGNAL_FUNC(dnd_data_received), NULL);
+ /* A packet is selected. */
+ set_menus_for_selected_packet(cf);
}
+static void
+main_cf_cb_packet_unselected(capture_file *cf)
+{
+ /* Clear out the display of that packet. */
+ clear_tree_and_hex_views();
+
+ /* No packet is selected. */
+ set_menus_for_selected_packet(cf);
+}
+
+static void
+main_cf_cb_field_unselected(capture_file *cf)
+{
+ statusbar_pop_field_msg();
+ set_menus_for_selected_tree_row(cf);
+}
+
+static void
+main_cf_cb_file_safe_started(gchar * filename)
+{
+ const gchar *name_ptr;
+ gchar *save_msg;
+
+ name_ptr = get_basename(filename);
+
+ save_msg = g_strdup_printf(" Saving: %s...", name_ptr);
+
+ statusbar_push_file_msg(save_msg);
+ g_free(save_msg);
+}
+
+static void
+main_cf_cb_file_safe_finished(gpointer data _U_)
+{
+ /* Pop the "Saving:" message off the status bar. */
+ statusbar_pop_file_msg();
+}
+
+static void
+main_cf_cb_file_safe_failed(gpointer data _U_)
+{
+ /* Pop the "Saving:" message off the status bar. */
+ statusbar_pop_file_msg();
+}
+
+static void
+main_cf_cb_file_safe_reload_finished(gpointer data _U_)
+{
+ set_menus_for_unsaved_capture_file(FALSE);
+}
+
+void main_cf_callback(gint event, gpointer data, gpointer user_data _U_)
+{
+ switch(event) {
+ case(cf_cb_file_closed):
+ main_cf_cb_file_closed(data);
+ break;
+ case(cf_cb_file_read_start):
+ main_cf_cb_file_read_start(data);
+ break;
+ case(cf_cb_file_read_finished):
+ main_cf_cb_file_read_finished(data);
+ break;
+#ifdef HAVE_LIBPCAP
+ case(cf_cb_live_capture_prepare):
+ main_cf_cb_live_capture_prepare(data);
+ break;
+ case(cf_cb_live_capture_started):
+ main_cf_cb_live_capture_started(data);
+ break;
+ case(cf_cb_live_capture_finished):
+ main_cf_cb_live_capture_finished(data);
+ break;
+#endif
+ case(cf_cb_packet_selected):
+ main_cf_cb_packet_selected(data);
+ break;
+ case(cf_cb_packet_unselected):
+ main_cf_cb_packet_unselected(data);
+ break;
+ case(cf_cb_field_unselected):
+ main_cf_cb_field_unselected(data);
+ break;
+ case(cf_cb_file_safe_started):
+ main_cf_cb_file_safe_started(data);
+ break;
+ case(cf_cb_file_safe_finished):
+ main_cf_cb_file_safe_finished(data);
+ break;
+ case(cf_cb_file_safe_reload_finished):
+ main_cf_cb_file_safe_reload_finished(data);
+ break;
+ case(cf_cb_file_safe_failed):
+ main_cf_cb_file_safe_failed(data);
+ break;
+ default:
+ g_warning("main_cf_callback: event %u unknown", event);
+ g_assert_not_reached();
+ }
+}
/* And now our feature presentation... [ fade to music ] */
int
main(int argc, char *argv[])
{
#ifdef HAVE_LIBPCAP
- char *command_name;
+ const char *command_name;
#endif
char *s;
int i;
extern char *optarg;
gboolean arg_error = FALSE;
-#ifdef WIN32
+#ifdef _WIN32
WSADATA wsaData;
-#endif /* WIN32 */
+#endif /* _WIN32 */
char *rf_path;
int rf_open_errno;
int err;
#ifdef HAVE_LIBPCAP
gboolean start_capture = FALSE;
- gchar *save_file = NULL;
GList *if_list;
if_info_t *if_info;
GList *lt_list, *lt_entry;
data_link_info_t *data_link_info;
gchar err_str[PCAP_ERRBUF_SIZE];
+ gchar *cant_get_if_list_errstr;
gboolean stats_known;
struct pcap_stat stats;
#else
gboolean rfilter_parse_failed = FALSE;
e_prefs *prefs;
char badopt;
-#if GTK_MAJOR_VERSION < 2
- char *bold_font_name;
-#endif
ethereal_tap_list *tli = NULL;
gchar *tap_opt = NULL;
+ GtkWidget *splash_win = NULL;
-#define OPTSTRING_INIT "a:b:B:c:f:hi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
+#define OPTSTRING_INIT "a:b:B:c:f:Hhi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
#ifdef HAVE_LIBPCAP
-#ifdef WIN32
+#ifdef _WIN32
#define OPTSTRING_CHILD "W:Z:"
#else
#define OPTSTRING_CHILD "W:"
-#endif /* WIN32 */
+#endif /* _WIN32 */
#else
#define OPTSTRING_CHILD ""
#endif /* HAVE_LIBPCAP */
char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
OPTSTRING_INIT;
+
+ /* Set the current locale according to the program environment.
+ * We haven't localized anything, but some GTK widgets are localized
+ * (the file selection dialogue, for example).
+ * This also sets the C-language locale to the native environment. */
+ gtk_set_locale();
+
+ /* Let GTK get its args */
+ gtk_init (&argc, &argv);
+
+ cf_callback_add(main_cf_callback, NULL);
+
+#if GTK_MAJOR_VERSION < 2 && GTK_MINOR_VERSION < 3
+ /* initialize our GTK eth_clist_type */
+ init_eth_clist_type();
+#endif
+
ethereal_path = argv[0];
-#ifdef WIN32
+#ifdef _WIN32
/* Arrange that if we have no console window, and a GLib message logging
routine is called to log a message, we pop up a console window.
#endif
#ifdef HAVE_LIBPCAP
+ /* Set the initial values in the capture_opts. This might be overwritten
+ by preference settings and then again by the command line parameters. */
+ capture_opts_init(capture_opts, &cfile);
+
+ capture_opts->snaplen = MIN_PACKET_SIZE;
+ capture_opts->has_ring_num_files = TRUE;
+
command_name = get_basename(ethereal_path);
/* Set "capture_child" to indicate whether this is going to be a child
process for a "-S" capture. */
- capture_child = (strcmp(command_name, CHILD_NAME) == 0);
- if (capture_child)
+ capture_opts->capture_child = (strcmp(command_name, CHILD_NAME) == 0);
+ if (capture_opts->capture_child) {
strcat(optstring, OPTSTRING_CHILD);
+ }
+#endif
+
+ /* We want a splash screen only if we're not a child process */
+ /* We also want it only if we're not being run with "-G".
+ XXX - we also don't want it if we're being run with
+ "-h" or "-v", as those are options to run Ethereal and just
+ have it print stuff to the command line. That would require
+ that we parse the argument list before putting up the splash
+ screen, which means we'd need to do so before reading the
+ preference files, as that could take enough time that we'd
+ want the splash screen up while we're doing that. Unfortunately,
+ that means we'd have to queue up, for example, "-o" options,
+ so that we apply them *after* reading the preferences, as
+ they're supposed to override saved preferences. */
+ if ((argc < 2 || strcmp(argv[1], "-G") != 0)
+#ifdef HAVE_LIBPCAP
+ && !capture_opts->capture_child
#endif
+ ) {
+ splash_win = splash_new("Loading Ethereal ...");
+ }
+
+ splash_update(splash_win, "Registering dissectors ...");
/* Register all dissectors; we must do this before checking for the
"-G" flag, as the "-G" flag dumps information registered by the
epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs,
failure_alert_box,open_failure_alert_box,read_failure_alert_box);
+ splash_update(splash_win, "Registering tap listeners ...");
+
/* Register all tap listeners; we do this before we parse the arguments,
as the "-z" argument can specify a registered tap. */
register_all_tap_listeners();
+ splash_update(splash_win, "Loading module preferences ...");
+
/* Now register the preferences for any non-dissector modules.
We must do that before we read the preferences as well. */
prefs_register_modules();
to specify the information to dump;
arguments after that will not be used. */
- if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
- if (argc == 2)
- proto_registrar_dump_fields();
- else {
- if (strcmp(argv[2], "fields") == 0)
- proto_registrar_dump_fields();
- else if (strcmp(argv[2], "protocols") == 0)
- proto_registrar_dump_protocols();
- else {
- fprintf(stderr, "ethereal: Invalid \"%s\" option for -G flag\n",
- argv[2]);
- exit(1);
- }
- }
- exit(0);
- }
+ handle_dashG_option(argc, argv, "ethereal");
/* multithread support currently doesn't seem to work in win32 gtk2.0.6 */
-#if ! defined WIN32 && GTK_MAJOR_VERSION >= 2 && defined G_THREADS_ENABLED && defined USE_THREADS
+#if !defined(_WIN32) && GTK_MAJOR_VERSION >= 2 && defined(G_THREADS_ENABLED) && defined USE_THREADS
{
GThread *ut;
g_thread_init(NULL);
ut=g_thread_create(update_thread, NULL, FALSE, NULL);
g_thread_set_priority(ut, G_THREAD_PRIORITY_LOW);
}
-#else /* WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
+#else /* _WIN32 || GTK1.2 || !G_THREADS_ENABLED || !USE_THREADS */
/* this is to keep tap extensions updating once every 3 seconds */
gtk_timeout_add(3000, (GtkFunction)update_cb,(gpointer)NULL);
-#endif /* !WIN32 && GTK2 && G_THREADS_ENABLED */
+#endif /* !_WIN32 && GTK2 && G_THREADS_ENABLED */
#if HAVE_GNU_ADNS
gtk_timeout_add(750, (GtkFunction) host_name_lookup_process, NULL);
#endif
-
- /* Set the current locale according to the program environment.
- * We haven't localized anything, but some GTK widgets are localized
- * (the file selection dialogue, for example).
- * This also sets the C-language locale to the native environment. */
- gtk_set_locale();
-
- /* Let GTK get its args */
- gtk_init (&argc, &argv);
+ splash_update(splash_win, "Loading configuration files ...");
/* Read the preference files. */
prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
}
#ifdef _WIN32
+ /* if the user wants a console to be always there, well, we should open one for him */
if (prefs->gui_console_open == console_open_always) {
create_console();
}
#endif
#ifdef HAVE_LIBPCAP
- capture_opts.has_snaplen = FALSE;
- capture_opts.snaplen = MIN_PACKET_SIZE;
- capture_opts.linktype = -1;
-#ifdef _WIN32
- capture_opts.buffer_size = 1;
-#endif
-
- capture_opts.has_autostop_packets = FALSE;
- capture_opts.autostop_packets = 1;
- capture_opts.has_autostop_duration = FALSE;
- capture_opts.autostop_duration = 1;
- capture_opts.has_autostop_filesize = FALSE;
- capture_opts.autostop_filesize = 1;
- capture_opts.has_autostop_files = FALSE;
- capture_opts.autostop_files = 1;
-
- capture_opts.multi_files_on = FALSE;
- capture_opts.has_ring_num_files = TRUE;
- capture_opts.ring_num_files = 2;
- capture_opts.has_file_duration = FALSE;
- capture_opts.file_duration = 1;
-
/* If this is a capture child process, it should pay no attention
to the "prefs.capture_prom_mode" setting in the preferences file;
it should do what the parent process tells it to do, and if
tell it so with a "-p" flag.
Otherwise, set promiscuous mode from the preferences setting. */
- if (capture_child)
- capture_opts.promisc_mode = TRUE;
- else
- capture_opts.promisc_mode = prefs->capture_prom_mode;
-
- /* Set "Update list of packets in real time" mode from the preferences
- setting. */
- capture_opts.sync_mode = prefs->capture_real_time;
+ /* the same applies to other preferences settings as well. */
+ if (capture_opts->capture_child) {
+ auto_scroll_live = FALSE;
+ } else {
+ capture_opts->promisc_mode = prefs->capture_prom_mode;
+ capture_opts->show_info = prefs->capture_show_info;
+ capture_opts->sync_mode = prefs->capture_real_time;
+ auto_scroll_live = prefs->capture_auto_scroll;
+ }
- /* And do the same for "Automatic scrolling in live capture" mode. */
- auto_scroll_live = prefs->capture_auto_scroll;
-#endif
+#endif /* HAVE_LIBPCAP */
/* Set the name resolution code's flags from the preferences. */
g_resolv_flags = prefs->name_resolve;
init_cap_file(&cfile);
-#ifdef WIN32
+#ifdef _WIN32
/* Load wpcap if possible. Do this before collecting the run-time version information */
load_wpcap();
/* Start windows sockets */
WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
-#endif /* WIN32 */
+#endif /* _WIN32 */
/* Assemble the compile-time version information string */
comp_info_str = g_string_new("Compiled ");
/* Now get our args */
while ((opt = getopt(argc, argv, optstring)) != -1) {
switch (opt) {
+ /*** capture option specific ***/
case 'a': /* autostop criteria */
+ case 'b': /* Ringbuffer option */
+ case 'c': /* Capture xxx packets */
+ case 'f': /* capture filter */
+ case 'k': /* Start capture immediately */
+ case 'H': /* Hide capture info dialog box */
+ case 'i': /* Use interface xxx */
+ case 'p': /* Don't capture in promiscuous mode */
+ case 'Q': /* Quit after capture (just capture to file) */
+ case 's': /* Set the snapshot (capture) length */
+ case 'S': /* "Sync" mode: used for following file ala tail -f */
+ case 'w': /* Write to capture file xxx */
+ case 'y': /* Set the pcap data link type */
+#ifdef _WIN32
+ /* Hidden option supporting Sync mode */
+ case 'Z': /* Write to pipe FD XXX */
+#endif /* _WIN32 */
#ifdef HAVE_LIBPCAP
- if (set_autostop_criterion(optarg) == FALSE) {
- fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
- exit(1);
- }
+ capture_opts_add_opt(capture_opts, "ethereal", opt, optarg, &start_capture);
#else
capture_option_specified = TRUE;
arg_error = TRUE;
#endif
break;
- case 'b': /* Ringbuffer option */
#ifdef HAVE_LIBPCAP
- capture_opts.multi_files_on = TRUE;
- capture_opts.has_ring_num_files = TRUE;
- if (get_ring_arguments(optarg) == FALSE) {
- fprintf(stderr, "ethereal: Invalid or unknown -b arg \"%s\"\n", optarg);
- exit(1);
- }
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
+ /* This is a hidden option supporting Sync mode, so we don't set
+ * the error flags for the user in the non-libpcap case.
+ */
+ case 'W': /* Write to capture file FD xxx */
+ capture_opts_add_opt(capture_opts, "ethereal", opt, optarg, &start_capture);
+ break;
#endif
- break;
+
+ /*** all non capture option specific ***/
case 'B': /* Byte view pane height */
bv_size = get_positive_int(optarg, "byte view pane height");
break;
- case 'c': /* Capture xxx packets */
-#ifdef HAVE_LIBPCAP
- capture_opts.has_autostop_packets = TRUE;
- capture_opts.autostop_packets = get_positive_int(optarg, "packet count");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'f':
-#ifdef HAVE_LIBPCAP
- if (cfile.cfilter)
- g_free(cfile.cfilter);
- cfile.cfilter = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'h': /* Print help and exit */
print_usage(TRUE);
exit(0);
break;
- case 'i': /* Use interface xxx */
-#ifdef HAVE_LIBPCAP
- cfile.iface = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'k': /* Start capture immediately */
-#ifdef HAVE_LIBPCAP
- start_capture = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'l': /* Automatic scrolling in live capture mode */
#ifdef HAVE_LIBPCAP
auto_scroll_live = TRUE;
break;
}
break;
- case 'p': /* Don't capture in promiscuous mode */
-#ifdef HAVE_LIBPCAP
- capture_opts.promisc_mode = FALSE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'P': /* Packet list pane height */
pl_size = get_positive_int(optarg, "packet list pane height");
break;
- case 'Q': /* Quit after capture (just capture to file) */
-#ifdef HAVE_LIBPCAP
- quit_after_cap = TRUE;
- start_capture = TRUE; /*** -Q implies -k !! ***/
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 'r': /* Read capture file xxx */
/* We may set "last_open_dir" to "cf_name", and if we change
"last_open_dir" later, we free the old value, so we have to
case 'R': /* Read file filter */
rfilter = optarg;
break;
- case 's': /* Set the snapshot (capture) length */
-#ifdef HAVE_LIBPCAP
- capture_opts.has_snaplen = TRUE;
- capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'S': /* "Sync" mode: used for following file ala tail -f */
-#ifdef HAVE_LIBPCAP
- capture_opts.sync_mode = TRUE;
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
case 't': /* Time stamp type */
if (strcmp(optarg, "r") == 0)
set_timestamp_setting(TS_RELATIVE);
break;
case 'v': /* Show version and exit */
show_version();
-#ifdef WIN32
+#ifdef _WIN32
destroy_console();
#endif
exit(0);
break;
- case 'w': /* Write to capture file xxx */
-#ifdef HAVE_LIBPCAP
- save_file = g_strdup(optarg);
-#else
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif
- break;
- case 'y': /* Set the pcap data link type */
-#ifdef HAVE_LIBPCAP
-#ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL
- capture_opts.linktype = pcap_datalink_name_to_val(optarg);
- if (capture_opts.linktype == -1) {
- fprintf(stderr, "ethereal: The specified data link type \"%s\" is not valid\n",
- optarg);
- exit(1);
- }
-#else /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
- /* XXX - just treat it as a number */
- capture_opts.linktype = get_natural_int(optarg, "data link type");
-#endif /* HAVE_PCAP_DATALINK_NAME_TO_VAL */
-#else /* HAVE_LIBPCAP */
- capture_option_specified = TRUE;
- arg_error = TRUE;
-#endif /* HAVE_LIBPCAP */
- break;
-#ifdef HAVE_LIBPCAP
- /* This is a hidden option supporting Sync mode, so we don't set
- * the error flags for the user in the non-libpcap case.
- */
- case 'W': /* Write to capture file FD xxx */
- cfile.save_file_fd = atoi(optarg);
- break;
-#endif
case 'z':
for(tli=tap_list;tli;tli=tli->next){
if(!strncmp(tli->cmd,optarg,strlen(tli->cmd))){
exit(1);
}
break;
-
-#ifdef _WIN32
-#ifdef HAVE_LIBPCAP
- /* Hidden option supporting Sync mode */
- case 'Z': /* Write to pipe FD XXX */
- /* associate stdout with pipe */
- i = atoi(optarg);
- if (dup2(i, 1) < 0) {
- fprintf(stderr, "Unable to dup pipe handle\n");
- exit(1);
- }
- break;
-#endif /* HAVE_LIBPCAP */
-#endif /* _WIN32 */
-
default:
case '?': /* Bad flag - print usage message */
arg_error = TRUE;
argv++;
}
+
+
if (argc != 0) {
/*
* Extra command line arguments were specified; complain.
arg_error = TRUE;
}
+ if (arg_error) {
#ifndef HAVE_LIBPCAP
- if (capture_option_specified)
- fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
+ if (capture_option_specified) {
+ fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
+ }
#endif
- if (arg_error) {
print_usage(FALSE);
exit(1);
}
#ifdef HAVE_LIBPCAP
if (start_capture && list_link_layer_types) {
/* Specifying *both* is bogus. */
- fprintf(stderr, "ethereal: You cannot specify both -L and a live capture.\n");
+ fprintf(stderr, "ethereal: You can't specify both -L and a live capture.\n");
exit(1);
}
did the user also specify a capture file to be read? */
if (cf_name) {
/* Yes - that's bogus. */
- fprintf(stderr, "ethereal: You cannot specify -L and a capture file to be read.\n");
+ fprintf(stderr, "ethereal: You can't specify -L and a capture file to be read.\n");
exit(1);
}
/* No - did they specify a ring buffer option? */
- if (capture_opts.multi_files_on) {
- fprintf(stderr, "ethereal: Ring buffer requested, but a capture is not being done.\n");
+ if (capture_opts->multi_files_on) {
+ fprintf(stderr, "ethereal: Ring buffer requested, but a capture isn't being done.\n");
exit(1);
}
} else {
a capture file to be read? */
if (start_capture && cf_name) {
/* Yes - that's bogus. */
- fprintf(stderr, "ethereal: You cannot specify both a live capture and a capture file to be read.\n");
+ fprintf(stderr, "ethereal: You can't specify both a live capture and a capture file to be read.\n");
exit(1);
}
/* No - was the ring buffer option specified and, if so, does it make
sense? */
- if (capture_opts.multi_files_on) {
+ if (capture_opts->multi_files_on) {
/* Ring buffer works only under certain conditions:
a) ring buffer does not work with temporary files;
- b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive -
+ b) sync_mode and capture_opts->ringbuffer_on are mutually exclusive -
sync_mode takes precedence;
c) it makes no sense to enable the ring buffer if the maximum
file size is set to "infinite". */
- if (save_file == NULL) {
+ if (capture_opts->save_file == NULL) {
fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
- capture_opts.multi_files_on = FALSE;
+ capture_opts->multi_files_on = FALSE;
}
- if (capture_opts.sync_mode) {
+ if (capture_opts->sync_mode) {
fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
- capture_opts.multi_files_on = FALSE;
+ capture_opts->multi_files_on = FALSE;
}
- if (!capture_opts.has_autostop_filesize) {
+ if (!capture_opts->has_autostop_filesize) {
fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
- capture_opts.multi_files_on = FALSE;
+ capture_opts->multi_files_on = FALSE;
}
}
}
if (start_capture || list_link_layer_types) {
/* Did the user specify an interface to use? */
- if (cfile.iface == NULL) {
+ if (capture_opts->iface == NULL) {
/* No - is a default specified in the preferences file? */
if (prefs->capture_device != NULL) {
/* Yes - use it. */
- cfile.iface = g_strdup(prefs->capture_device);
+ capture_opts->iface = g_strdup(prefs->capture_device);
} else {
/* No - pick the first one from the list of interfaces. */
if_list = get_interface_list(&err, err_str);
switch (err) {
case CANT_GET_INTERFACE_LIST:
- fprintf(stderr, "ethereal: Can't get list of interfaces: %s\n",
- err_str);
+ cant_get_if_list_errstr = cant_get_if_list_error_message(err_str);
+ fprintf(stderr, "%s\n", cant_get_if_list_errstr);
+ g_free(cant_get_if_list_errstr);
break;
case NO_INTERFACES_FOUND:
exit(2);
}
if_info = if_list->data; /* first interface */
- cfile.iface = g_strdup(if_info->name);
+ capture_opts->iface = g_strdup(if_info->name);
free_interface_list(if_list);
}
}
}
- if (capture_child) {
- if (cfile.save_file_fd == -1) {
+ if (capture_opts->capture_child) {
+ if (capture_opts->save_file_fd == -1) {
/* XXX - send this to the standard output as something our parent
should put in an error message box? */
fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
if (list_link_layer_types) {
/* Get the list of link-layer types for the capture device. */
- lt_list = get_pcap_linktype_list(cfile.iface, err_str);
+ lt_list = get_pcap_linktype_list(capture_opts->iface, err_str);
if (lt_list == NULL) {
if (err_str[0] != '\0') {
fprintf(stderr, "ethereal: The list of data link types for the capture device could not be obtained (%s).\n"
exit(0);
}
+ if (capture_opts->has_snaplen) {
+ if (capture_opts->snaplen < 1)
+ capture_opts->snaplen = WTAP_MAX_PACKET_SIZE;
+ else if (capture_opts->snaplen < MIN_PACKET_SIZE)
+ capture_opts->snaplen = MIN_PACKET_SIZE;
+ }
+
+ /* Check the value range of the ringbuffer_num_files parameter */
+ if (capture_opts->ring_num_files > RINGBUFFER_MAX_NUM_FILES)
+ capture_opts->ring_num_files = RINGBUFFER_MAX_NUM_FILES;
+#if RINGBUFFER_MIN_NUM_FILES > 0
+ else if (capture_opts->num_files < RINGBUFFER_MIN_NUM_FILES)
+ capture_opts->ring_num_files = RINGBUFFER_MIN_NUM_FILES;
#endif
+#endif /* HAVE_LIBPCAP */
/* Notify all registered modules that have had any of their preferences
changed either from one of the preferences file or from the command
}
}
-#ifdef HAVE_LIBPCAP
- if (capture_opts.has_snaplen) {
- if (capture_opts.snaplen < 1)
- capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
- else if (capture_opts.snaplen < MIN_PACKET_SIZE)
- capture_opts.snaplen = MIN_PACKET_SIZE;
- }
-
- /* Check the value range of the ringbuffer_num_files parameter */
- if (capture_opts.ring_num_files > RINGBUFFER_MAX_NUM_FILES)
- capture_opts.ring_num_files = RINGBUFFER_MAX_NUM_FILES;
-#if RINGBUFFER_MIN_NUM_FILES > 0
- else if (capture_opts.num_files < RINGBUFFER_MIN_NUM_FILES)
- capture_opts.ring_num_files = RINGBUFFER_MIN_NUM_FILES;
-#endif
-#endif
-
-#ifdef WIN32
-#if GTK_MAJOR_VERSION >= 2
- try_to_get_windows_font_gtk2();
-#endif
-#endif
-
/* read in rc file from global and personal configuration paths. */
+ /* XXX - is this a good idea? */
gtk_rc_parse(RC_FILE);
rc_file = get_persconffile_path(RC_FILE, FALSE);
gtk_rc_parse(rc_file);
- /* Try to load the regular and boldface fixed-width fonts */
-#if GTK_MAJOR_VERSION < 2
- bold_font_name = font_boldify(prefs->gui_font_name1);
- m_r_font = gdk_font_load(prefs->gui_font_name1);
- m_b_font = gdk_font_load(bold_font_name);
- if (m_r_font == NULL || m_b_font == NULL) {
- /* XXX - pop this up as a dialog box? no */
- if (m_r_font == NULL) {
#ifdef HAVE_LIBPCAP
- if (!capture_child)
-#endif
- fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
- prefs->gui_font_name1);
- } else {
- gdk_font_unref(m_r_font);
- }
- if (m_b_font == NULL) {
-#ifdef HAVE_LIBPCAP
- if (!capture_child)
-#endif
- fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
- bold_font_name);
- } else {
- gdk_font_unref(m_b_font);
- }
- g_free(bold_font_name);
- if ((m_r_font = gdk_font_load("6x13")) == NULL) {
- fprintf(stderr, "ethereal: Error: font 6x13 not found\n");
- exit(1);
- }
- if ((m_b_font = gdk_font_load("6x13bold")) == NULL) {
- fprintf(stderr, "ethereal: Error: font 6x13bold not found\n");
- exit(1);
- }
- g_free(prefs->gui_font_name1);
- prefs->gui_font_name1 = g_strdup("6x13");
- }
-#else /* GTK_MAJOR_VERSION */
- m_r_font = pango_font_description_from_string(prefs->gui_font_name2);
- m_b_font = pango_font_description_copy(m_r_font);
- pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
- if (m_r_font == NULL || m_b_font == NULL) {
- /* XXX - pop this up as a dialog box? no */
- if (m_r_font == NULL) {
-#ifdef HAVE_LIBPCAP
- if (!capture_child)
-#endif
- fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to Monospace 9\n",
- prefs->gui_font_name2);
- } else {
- pango_font_description_free(m_r_font);
- }
- if (m_b_font == NULL) {
-#ifdef HAVE_LIBPCAP
- if (!capture_child)
-#endif
- fprintf(stderr, "ethereal: Warning: bold font %s not found - defaulting"
- " to Monospace 9\n", prefs->gui_font_name2);
- } else {
- pango_font_description_free(m_b_font);
- }
- if ((m_r_font = pango_font_description_from_string("Monospace 9")) == NULL)
- {
- fprintf(stderr, "ethereal: Error: font Monospace 9 not found\n");
- exit(1);
- }
- if ((m_b_font = pango_font_description_copy(m_r_font)) == NULL) {
- fprintf(stderr, "ethereal: Error: font Monospace 9 bold not found\n");
- exit(1);
- }
- g_free(prefs->gui_font_name2);
- pango_font_description_set_weight(m_b_font, PANGO_WEIGHT_BOLD);
- prefs->gui_font_name2 = g_strdup("Monospace 9");
- }
-#endif /* GTK_MAJOR_VERSION */
-
- /* Call this for the side-effects that set_fonts() produces */
- set_fonts(m_r_font, m_b_font);
-
-#ifdef HAVE_LIBPCAP
- /* Is this a "child" ethereal, which is only supposed to pop up a
- capture box to let us stop the capture, and run a capture
- to a file that our parent will read? */
- if (!capture_child) {
-#endif
- /* No. Pop up the main window, and read in a capture file if
- we were told to. */
- create_main_window(pl_size, tv_size, bv_size, prefs);
-
- /* Read the recent file, as we have the gui now ready for it. */
- read_recent(&rf_path, &rf_open_errno);
-
- /* rearrange all the widgets */
- main_widgets_rearrange();
-
- /* Fill in column titles. This must be done after the top level window
- is displayed.
-
- XXX - is that still true, with fixed-width columns? */
- packet_list_set_column_titles();
-
- menu_recent_read_finished();
+ font_init(capture_opts->capture_child);
+#else
+ font_init(FALSE);
+#endif
- switch (font_apply()) {
- case FA_SUCCESS:
- break;
- case FA_FONT_NOT_RESIZEABLE:
- /* "font_apply()" popped up an alert box. */
- /* turn off zooming - font can't be resized */
- case FA_FONT_NOT_AVAILABLE:
- /* XXX - did we successfully load the un-zoomed version earlier?
- If so, this *probably* means the font is available, but not at
- this particular zoom level, but perhaps some other failure
- occurred; I'm not sure you can determine which is the case,
- however. */
- /* turn off zooming - zoom level is unavailable */
- default:
- /* in any other case than FA_SUCCESS, turn off zooming */
- recent.gui_zoom_level = 0;
- /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
- }
+ /* close the splash screen, as we are going to open the main window now */
+ splash_destroy(splash_win);
- dnd_init(top_level);
- colors_init();
- colfilter_init();
+#ifdef HAVE_LIBPCAP
+ /* Is this a "child" ethereal, which is only supposed to pop up a
+ capture box to let us stop the capture, and run a capture
+ to a file that our parent will read? */
+ if (capture_opts->capture_child) {
+ /* This is the child process for a sync mode or fork mode capture,
+ so just do the low-level work of a capture - don't create
+ a temporary file and fork off *another* child process (so don't
+ call "do_capture()"). */
- /* the window can be sized only, if it's not already shown, so do it now! */
- main_load_window_geometry(top_level);
+ /* Pop up any queued-up alert boxes. */
+ display_queued_messages();
- /*** we have finished all init things, show the main window ***/
- gtk_widget_show(top_level);
+ /* XXX - hand these stats to the parent process */
+ capture_start(capture_opts, &stats_known, &stats);
- /* the window can be maximized only, if it's visible, so do it after show! */
- main_load_window_geometry(top_level);
+ /* The capture is done; there's nothing more for us to do. */
+ gtk_exit(0);
+ }
+#endif
- /* process all pending GUI events before continue */
- while (gtk_events_pending()) gtk_main_iteration();
+ /***********************************************************************/
+ /* Everything is prepared now, preferences and command line was read in,
+ we are NOT a child window for a synced capture. */
+
+ /* Pop up the main window, and read in a capture file if
+ we were told to. */
+ create_main_window(pl_size, tv_size, bv_size, prefs);
+
+ /* Read the recent file, as we have the gui now ready for it. */
+ read_recent(&rf_path, &rf_open_errno);
+
+ /* rearrange all the widgets as we now have the recent settings for this */
+ main_widgets_rearrange();
+
+ /* Fill in column titles. This must be done after the top level window
+ is displayed.
+
+ XXX - is that still true, with fixed-width columns? */
+ packet_list_set_column_titles();
+
+ menu_recent_read_finished();
+
+ switch (user_font_apply()) {
+ case FA_SUCCESS:
+ break;
+ case FA_FONT_NOT_RESIZEABLE:
+ /* "user_font_apply()" popped up an alert box. */
+ /* turn off zooming - font can't be resized */
+ case FA_FONT_NOT_AVAILABLE:
+ /* XXX - did we successfully load the un-zoomed version earlier?
+ If so, this *probably* means the font is available, but not at
+ this particular zoom level, but perhaps some other failure
+ occurred; I'm not sure you can determine which is the case,
+ however. */
+ /* turn off zooming - zoom level is unavailable */
+ default:
+ /* in any other case than FA_SUCCESS, turn off zooming */
+ recent.gui_zoom_level = 0;
+ /* XXX: would it be a good idea to disable zooming (insensitive GUI)? */
+ }
- /* Pop up any queued-up alert boxes. */
- display_queued_messages();
+ dnd_init(top_level);
+
+ colors_init();
+ colfilter_init();
+ decode_as_init();
+
+ /* the window can be sized only, if it's not already shown, so do it now! */
+ main_load_window_geometry(top_level);
+
+ /* If we were given the name of a capture file, read it in now;
+ we defer it until now, so that, if we can't open it, and pop
+ up an alert box, the alert box is more likely to come up on
+ top of the main window - but before the preference-file-error
+ alert box, so, if we get one of those, it's more likely to come
+ up on top of us. */
+ if (cf_name) {
+ show_main_window(TRUE);
+ if (rfilter != NULL) {
+ if (!dfilter_compile(rfilter, &rfcode)) {
+ bad_dfilter_alert_box(rfilter);
+ rfilter_parse_failed = TRUE;
+ }
+ }
+ if (!rfilter_parse_failed) {
+ if (cf_open(&cfile, cf_name, FALSE, &err) == CF_OK) {
+ /* "cf_open()" succeeded, so it closed the previous
+ capture file, and thus destroyed any previous read filter
+ attached to "cf". */
- /* If we were given the name of a capture file, read it in now;
- we defer it until now, so that, if we can't open it, and pop
- up an alert box, the alert box is more likely to come up on
- top of the main window - but before the preference-file-error
- alert box, so, if we get one of those, it's more likely to come
- up on top of us. */
- if (cf_name) {
- if (rfilter != NULL) {
- if (!dfilter_compile(rfilter, &rfcode)) {
- bad_dfilter_alert_box(rfilter);
- rfilter_parse_failed = TRUE;
+ cfile.rfcode = rfcode;
+ /* Open tap windows; we do so after creating the main window,
+ to avoid GTK warnings, and after successfully opening the
+ capture file, so we know we have something to tap. */
+ if (tap_opt && tli) {
+ (*tli->func)(tap_opt);
+ g_free(tap_opt);
}
- }
- if (!rfilter_parse_failed) {
- if ((err = cf_open(cf_name, FALSE, &cfile)) == 0) {
- /* "cf_open()" succeeded, so it closed the previous
- capture file, and thus destroyed any previous read filter
- attached to "cf". */
- cfile.rfcode = rfcode;
-
- /* Open tap windows; we do so after creating the main window,
- to avoid GTK warnings, and after successfully opening the
- capture file, so we know we have something to tap. */
- if (tap_opt && tli) {
- (*tli->func)(tap_opt);
- g_free(tap_opt);
- }
- /* Read the capture file. */
- switch (cf_read(&cfile)) {
+ /* Read the capture file. */
+ switch (cf_read(&cfile)) {
- case READ_SUCCESS:
- case READ_ERROR:
- /* Just because we got an error, that doesn't mean we were unable
- to read any of the file; we handle what we could get from the
- file. */
- break;
+ case CF_READ_OK:
+ case CF_READ_ERROR:
+ /* Just because we got an error, that doesn't mean we were unable
+ to read any of the file; we handle what we could get from the
+ file. */
+ break;
- case READ_ABORTED:
- /* Exit now. */
- gtk_exit(0);
- break;
- }
- /* Save the name of the containing directory specified in the
- path name, if any; we can write over cf_name, which is a
- good thing, given that "get_dirname()" does write over its
- argument. */
- s = get_dirname(cf_name);
- /* we might already set this from the recent file, don't overwrite this */
- if(last_open_dir == NULL)
- set_last_open_dir(s);
- g_free(cf_name);
- cf_name = NULL;
- } else {
- if (rfcode != NULL)
- dfilter_free(rfcode);
- cfile.rfcode = NULL;
+ case CF_READ_ABORTED:
+ /* Exit now. */
+ gtk_exit(0);
+ break;
}
+ /* Save the name of the containing directory specified in the
+ path name, if any; we can write over cf_name, which is a
+ good thing, given that "get_dirname()" does write over its
+ argument. */
+ s = get_dirname(cf_name);
+ /* we might already set this from the recent file, don't overwrite this */
+ if(get_last_open_dir() == NULL)
+ set_last_open_dir(s);
+ g_free(cf_name);
+ cf_name = NULL;
+ } else {
+ if (rfcode != NULL)
+ dfilter_free(rfcode);
+ cfile.rfcode = NULL;
}
}
+ } else {
#ifdef HAVE_LIBPCAP
if (start_capture) {
+ if (capture_opts->save_file != NULL) {
+ /* Save the directory name for future file dialogs. */
+ /* (get_dirname overwrites filename) */
+ s = get_dirname(g_strdup(capture_opts->save_file));
+ set_last_open_dir(s);
+ g_free(s);
+ }
/* "-k" was specified; start a capture. */
- if (do_capture(save_file)) {
+ show_main_window(TRUE);
+ if (do_capture(capture_opts)) {
/* The capture started. Open tap windows; we do so after creating
the main window, to avoid GTK warnings, and after starting the
capture, so we know we have something to tap. */
g_free(tap_opt);
}
}
- if (save_file != NULL) {
- /* Save the directory name for future file dialogs. */
- s = get_dirname(save_file); /* Overwrites save_file */
- set_last_open_dir(s);
- g_free(save_file);
- save_file = NULL;
- }
}
else {
+ show_main_window(FALSE);
set_menus_for_capture_in_progress(FALSE);
}
- } else {
- /* This is the child process for a sync mode or fork mode capture,
- so just do the low-level work of a capture - don't create
- a temporary file and fork off *another* child process (so don't
- call "do_capture()"). */
-
- /* Pop up any queued-up alert boxes. */
- display_queued_messages();
-
- /* XXX - hand these stats to the parent process */
- capture(&stats_known, &stats);
- /* The capture is done; there's nothing more for us to do. */
- gtk_exit(0);
- }
- if (!start_capture && (cfile.cfilter == NULL || strlen(cfile.cfilter) == 0)) {
- if (cfile.cfilter) {
- g_free(cfile.cfilter);
+ /* if the user didn't supplied a capture filter, use the one to filter out remote connections like SSH */
+ if (!start_capture && (capture_opts->cfilter == NULL || strlen(capture_opts->cfilter) == 0)) {
+ if (capture_opts->cfilter) {
+ g_free(capture_opts->cfilter);
+ }
+ capture_opts->cfilter = g_strdup(get_conn_cfilter());
}
- cfile.cfilter = g_strdup(get_conn_cfilter());
- }
#else /* HAVE_LIBPCAP */
- set_menus_for_capture_in_progress(FALSE);
+ show_main_window(FALSE);
+ set_menus_for_capture_in_progress(FALSE);
#endif /* HAVE_LIBPCAP */
+ }
gtk_main();
epan_cleanup();
g_free(rc_file);
-#ifdef WIN32
+#ifdef _WIN32
/* Shutdown windows sockets */
WSACleanup();
return 0; /* not reached */
}
-#ifdef WIN32
+#ifdef _WIN32
/* We build this as a GUI subsystem application on Win32, so
"WinMain()", not "main()", gets called.
}
#endif
-#if GTK_MAJOR_VERSION < 2
-/* Given a font name, construct the name of the next heavier version of
- that font. */
-
-#define XLFD_WEIGHT 3 /* index of the "weight" field */
-
-/* Map from a given weight to the appropriate weight for the "bold"
- version of a font.
- XXX - the XLFD says these strings shouldn't be used for font matching;
- can we get the weight, as a number, from GDK, and ask GDK to find us
- a font just like the given font, but with the appropriate higher
- weight? */
-static const struct {
- char *light;
- char *heavier;
-} weight_map[] = {
- { "ultralight", "light" },
- { "extralight", "semilight" },
- { "light", "medium" },
- { "semilight", "semibold" },
- { "medium", "bold" },
- { "normal", "bold" },
- { "semibold", "extrabold" },
- { "bold", "ultrabold" }
-};
-#define N_WEIGHTS (sizeof weight_map / sizeof weight_map[0])
-
-char *
-font_boldify(const char *font_name)
-{
- char *bold_font_name;
- gchar **xlfd_tokens;
- unsigned int i;
-
- /* Is this an XLFD font? If it begins with "-", yes, otherwise no. */
- if (font_name[0] == '-') {
- xlfd_tokens = g_strsplit(font_name, "-", XLFD_WEIGHT+1);
-
- /*
- * Make sure we *have* a weight (this might not be a valid
- * XLFD font name).
- */
- for (i = 0; i < XLFD_WEIGHT+1; i++) {
- if (xlfd_tokens[i] == NULL) {
- /*
- * We don't, so treat this as a non-XLFD
- * font name.
- */
- goto not_xlfd;
- }
- }
- for (i = 0; i < N_WEIGHTS; i++) {
- if (strcmp(xlfd_tokens[XLFD_WEIGHT],
- weight_map[i].light) == 0) {
- g_free(xlfd_tokens[XLFD_WEIGHT]);
- xlfd_tokens[XLFD_WEIGHT] =
- g_strdup(weight_map[i].heavier);
- break;
- }
- }
- bold_font_name = g_strjoinv("-", xlfd_tokens);
- g_strfreev(xlfd_tokens);
- return bold_font_name;
- }
-
-not_xlfd:
- /*
- * This isn't an XLFD font name; just append "bold" to the name
- * of the font.
- */
- bold_font_name = g_strconcat(font_name, "bold", NULL);
- return bold_font_name;
-}
-#endif
-
-/* Given a font name, construct the name of a version of that font with
- the current zoom factor applied. */
-static char *
-font_zoom(char *gui_font_name)
-{
- char *new_font_name;
- char *font_name_dup;
- char *font_name_p;
- long font_point_size_l;
-#if GTK_MAJOR_VERSION < 2
- int minus_chars;
- char *font_foundry;
- char *font_family;
- char *font_weight;
- char *font_slant;
- char *font_set_width;
- char *font_add_style;
- char *font_pixel_size;
- char *font_point_size;
- char *font_res_x;
- char *font_res_y;
- char *font_spacing;
- char *font_aver_width;
- char *font_charset_reg;
- char *font_charset_encoding;
-#endif
-
- if (recent.gui_zoom_level == 0) {
- /* There is no zoom factor - just return the name, so that if
- this is GTK+ 1.2[.x] and the font name isn't an XLFD font
- name, we don't fail. */
- return g_strdup(gui_font_name);
- }
-
- font_name_dup = g_strdup(gui_font_name);
- font_name_p = font_name_dup;
-
-#if GTK_MAJOR_VERSION >= 2
- /* find the start of the font_size string */
- font_name_p = strrchr(font_name_dup, ' ');
- *font_name_p = '\0';
- font_name_p++;
-
- /* calculate the new font size */
- font_point_size_l = strtol(font_name_p, NULL, 10);
- font_point_size_l += recent.gui_zoom_level;
-
- /* build a new font name */
- new_font_name = g_strdup_printf("%s %ld", font_name_dup, font_point_size_l);
-#else
- minus_chars = 0;
- /* replace all '-' chars by NUL and count them */
- while ((font_name_p = strchr(font_name_p, '-')) != NULL) {
- *font_name_p = '\0';
- font_name_p++;
- minus_chars++;
- }
-
- if (minus_chars != 14) {
- /*
- * Not a valid XLFD font name.
- * XXX - can we try scaling it by looking for a size at the end
- * and tweaking that? Unfortunately, some fonts have numbers
- * at the end that aren't, as far as I know, sizes, e.g. "nil2".
- */
- return NULL;
- }
-
- /* first element (font name registry) empty */
- font_name_p = font_name_dup;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- /* get pointers to all font name elements */
- font_foundry = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_family = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_weight = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_slant = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_set_width = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_add_style = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_pixel_size = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_point_size = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_res_x = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_res_y = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_spacing = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_aver_width = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_charset_reg = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- font_charset_encoding = font_name_p;
- font_name_p += strlen(font_name_p);
- font_name_p++;
-
- /* calculate the new font size */
- font_point_size_l = strtol(font_point_size, NULL, 10);
- font_point_size_l += recent.gui_zoom_level*10;
- if (font_point_size_l <= 0)
- font_point_size_l = 10;
-
- /* build a new font name */
- new_font_name = g_strdup_printf("-%s-%s-%s-%s-%s-%s-%s-%ld-%s-%s-%s-%s-%s-%s",
- font_foundry, font_family, font_weight, font_slant, font_set_width,
- font_add_style, font_pixel_size, font_point_size_l, font_res_x,
- font_res_y, font_spacing, font_aver_width, font_charset_reg,
- font_charset_encoding);
-#endif
-
- g_free(font_name_dup);
-
- return new_font_name;
-}
-
-fa_ret_t
-font_apply(void) {
- char *gui_font_name;
-#if GTK_MAJOR_VERSION < 2
- GdkFont *new_r_font, *new_b_font;
- char *bold_font_name;
- GdkFont *old_r_font = NULL, *old_b_font = NULL;
-#else
- PangoFontDescription *new_r_font, *new_b_font;
- PangoFontDescription *old_r_font = NULL, *old_b_font = NULL;
-#endif
-
- /* convert font name to reflect the zoom level */
- gui_font_name = font_zoom(prefs.PREFS_GUI_FONT_NAME);
- if (gui_font_name == NULL) {
- /*
- * This means the font name isn't an XLFD font name.
- * We just report that for now as a font not available in
- * multiple sizes.
- */
- simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
- "Your current font isn't available in any other sizes.\n");
- return FA_FONT_NOT_RESIZEABLE;
- }
-
-#if GTK_MAJOR_VERSION < 2
- new_r_font = gdk_font_load(gui_font_name);
- bold_font_name = font_boldify(gui_font_name);
- new_b_font = gdk_font_load(bold_font_name);
-#else
- new_r_font = pango_font_description_from_string(gui_font_name);
- new_b_font = pango_font_description_copy(new_r_font);
- pango_font_description_set_weight(new_b_font, PANGO_WEIGHT_BOLD);
-#endif
- if (new_r_font == NULL || new_b_font == NULL) {
- /* We're no longer using the new fonts; unreference them. */
-#if GTK_MAJOR_VERSION < 2
- if (new_r_font != NULL)
- gdk_font_unref(new_r_font);
- if (new_b_font != NULL)
- gdk_font_unref(new_b_font);
-#else
- if (new_r_font != NULL)
- pango_font_description_free(new_r_font);
- if (new_b_font != NULL)
- pango_font_description_free(new_b_font);
-#endif
- g_free(gui_font_name);
-
- /* We let our caller pop up a dialog box, as the error message
- depends on the context (did they zoom in or out, or did they
- do something else? */
- return FA_FONT_NOT_AVAILABLE;
- }
-
- /* the font(s) seem to be ok */
- set_plist_font(new_r_font);
- set_ptree_font_all(new_r_font);
- old_r_font = m_r_font;
- old_b_font = m_b_font;
- set_fonts(new_r_font, new_b_font);
-#if GTK_MAJOR_VERSION < 2
- g_free(bold_font_name);
-#endif
-
- /* Redraw the hex dump windows. */
- redraw_hex_dump_all();
-
- /* Redraw the "Follow TCP Stream" windows. */
- follow_redraw_all();
-
- /* We're no longer using the old fonts; unreference them. */
-#if GTK_MAJOR_VERSION < 2
- if (old_r_font != NULL)
- gdk_font_unref(old_r_font);
- if (old_b_font != NULL)
- gdk_font_unref(old_b_font);
-#else
- if (old_r_font != NULL)
- pango_font_description_free(old_r_font);
- if (old_b_font != NULL)
- pango_font_description_free(old_b_font);
-#endif
- g_free(gui_font_name);
- return FA_SUCCESS;
-}
-
-
-#ifdef WIN32
-
-#define NAME_BUFFER_LEN 32
-
-#if GTK_MAJOR_VERSION < 2
-
-
-/* The setting of the MS default font for system stuff (menus, dialogs, ...),
- * coming from: Allin Cottrell, http://www.ecn.wfu.edu/~cottrell/gtk_win32,
- * Thank you very much for this! */
-int get_windows_font_gtk1(char *fontspec, int fontspec_len)
-{
- HDC h_dc;
- HGDIOBJ h_font;
- TEXTMETRIC tm;
- char name[NAME_BUFFER_LEN];
- int len, pix_height;
-
- h_dc = CreateDC("DISPLAY", NULL, NULL, NULL);
- if (h_dc == NULL) return 1;
- h_font = GetStockObject(DEFAULT_GUI_FONT);
- if (h_font == NULL || !SelectObject(h_dc, h_font)) {
- DeleteDC(h_dc);
- return 1;
- }
- len = GetTextFace(h_dc, NAME_BUFFER_LEN, name);
- if (len <= 0) {
- DeleteDC(h_dc);
- return 1;
- }
- if (!GetTextMetrics(h_dc, &tm)) {
- DeleteDC(h_dc);
- return 1;
- }
- pix_height = tm.tmHeight;
- DeleteDC(h_dc);
- g_snprintf(fontspec, fontspec_len, "-*-%s-*-*-*-*-%i-*-*-*-p-*-iso8859-1", name,
- pix_height);
- return 0;
-}
-
-void set_app_font_gtk1(GtkWidget *top_level_w)
-{
- GtkStyle *style;
- char winfont[80];
-
- style = gtk_widget_get_style(top_level);
- if (get_windows_font_gtk1(winfont, sizeof(winfont)) == 0)
- style->font = gdk_font_load(winfont);
- if (style->font) gtk_widget_set_style(top_level, style);
-}
-
-#else /* GTK_MAJOR_VERSION */
-static char appfontname[128] = "tahoma 8";
-
-void set_app_font_gtk2(const char *fontname)
-{
- GtkSettings *settings;
-
- if (fontname != NULL && *fontname == 0) return;
-
- settings = gtk_settings_get_default();
-
- if (fontname == NULL) {
- g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
- } else {
- GtkWidget *w;
- PangoFontDescription *pfd;
- PangoContext *pc;
- PangoFont *pfont;
-
- w = gtk_label_new(NULL);
- pfd = pango_font_description_from_string(fontname);
- pc = gtk_widget_get_pango_context(w);
- pfont = pango_context_load_font(pc, pfd);
-
- if (pfont != NULL) {
- strcpy(appfontname, fontname);
- g_object_set(G_OBJECT(settings), "gtk-font-name", appfontname, NULL);
- }
-
- gtk_widget_destroy(w);
- pango_font_description_free(pfd);
- }
-}
-
-char *default_windows_menu_fontspec_gtk2(void)
-{
- gchar *fontspec = NULL;
- NONCLIENTMETRICS ncm;
-
- memset(&ncm, 0, sizeof ncm);
- ncm.cbSize = sizeof ncm;
-
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0)) {
- HDC screen = GetDC(0);
- double y_scale = 72.0 / GetDeviceCaps(screen, LOGPIXELSY);
- int point_size = (int) (ncm.lfMenuFont.lfHeight * y_scale);
-
- if (point_size < 0) point_size = -point_size;
- fontspec = g_strdup_printf("%s %d", ncm.lfMenuFont.lfFaceName,
- point_size);
- ReleaseDC(0, screen);
- }
-
- return fontspec;
-}
-
-static void try_to_get_windows_font_gtk2(void)
-{
- gchar *fontspec;
-
- fontspec = default_windows_menu_fontspec_gtk2();
-
- if (fontspec != NULL) {
- int match = 0;
- PangoFontDescription *pfd;
- PangoFont *pfont;
- PangoContext *pc;
- GtkWidget *w;
-
- pfd = pango_font_description_from_string(fontspec);
-
- w = gtk_label_new(NULL);
- pc = gtk_widget_get_pango_context(w);
- pfont = pango_context_load_font(pc, pfd);
- match = (pfont != NULL);
-
- pango_font_description_free(pfd);
- g_object_unref(G_OBJECT(pc));
- gtk_widget_destroy(w);
-
- if (match) set_app_font_gtk2(fontspec);
- g_free(fontspec);
- }
-}
-#endif /* GTK_MAJOR_VERSION */
-
-#endif /* WIN32 */
GtkWidget *info_bar_new(void)
{
{
switch(layout_content) {
case(layout_pane_content_none):
- return none_lb;
+ return NULL;
break;
case(layout_pane_content_plist):
return pkt_scrollw;
* Rearrange the main window widgets
*/
void main_widgets_rearrange(void) {
- GtkWidget *pane_content[3];
+ GtkWidget *first_pane_widget1, *first_pane_widget2;
+ GtkWidget *second_pane_widget1, *second_pane_widget2;
+ gboolean split_top_left;
/* be a bit faster */
gtk_widget_hide(main_vbox);
gtk_widget_ref(info_bar);
gtk_widget_ref(packets_bar);
gtk_widget_ref(status_pane);
- gtk_widget_ref(none_lb);
gtk_widget_ref(main_pane_v1);
gtk_widget_ref(main_pane_v2);
gtk_widget_ref(main_pane_h1);
gtk_widget_ref(main_pane_h2);
+ gtk_widget_ref(welcome_pane);
/* empty all containers participating */
gtk_container_foreach(GTK_CONTAINER(main_vbox), foreach_remove_a_child, main_vbox);
gtk_box_pack_start(GTK_BOX(main_vbox), filter_tb, FALSE, TRUE, 1);
}
- /* get the corresponding widgets to the content setting */
- pane_content[0] = main_widget_layout(prefs.gui_layout_content_1);
- pane_content[1] = main_widget_layout(prefs.gui_layout_content_2);
- pane_content[2] = main_widget_layout(prefs.gui_layout_content_3);
-
/* fill the main layout panes */
switch(prefs.gui_layout_type) {
case(layout_type_5):
main_first_pane = main_pane_v1;
main_second_pane = main_pane_v2;
- gtk_paned_add1(GTK_PANED(main_first_pane), pane_content[0]);
- gtk_paned_add2(GTK_PANED(main_first_pane), main_second_pane);
- gtk_paned_pack1(GTK_PANED(main_second_pane), pane_content[1], TRUE, TRUE);
- gtk_paned_pack2(GTK_PANED(main_second_pane), pane_content[2], FALSE, FALSE);
+ split_top_left = FALSE;
break;
case(layout_type_2):
main_first_pane = main_pane_v1;
main_second_pane = main_pane_h1;
- gtk_paned_add1(GTK_PANED(main_first_pane), pane_content[0]);
- gtk_paned_add2(GTK_PANED(main_first_pane), main_second_pane);
- gtk_paned_pack1(GTK_PANED(main_second_pane), pane_content[1], TRUE, TRUE);
- gtk_paned_pack2(GTK_PANED(main_second_pane), pane_content[2], FALSE, FALSE);
+ split_top_left = FALSE;
break;
case(layout_type_1):
main_first_pane = main_pane_v1;
main_second_pane = main_pane_h1;
- gtk_paned_add1(GTK_PANED(main_first_pane), main_second_pane);
- gtk_paned_add2(GTK_PANED(main_first_pane), pane_content[2]);
- gtk_paned_pack1(GTK_PANED(main_second_pane), pane_content[0], TRUE, TRUE);
- gtk_paned_pack2(GTK_PANED(main_second_pane), pane_content[1], FALSE, FALSE);
+ split_top_left = TRUE;
break;
case(layout_type_4):
main_first_pane = main_pane_h1;
main_second_pane = main_pane_v1;
- gtk_paned_add1(GTK_PANED(main_first_pane), pane_content[0]);
- gtk_paned_add2(GTK_PANED(main_first_pane), main_second_pane);
- gtk_paned_pack1(GTK_PANED(main_second_pane), pane_content[1], TRUE, TRUE);
- gtk_paned_pack2(GTK_PANED(main_second_pane), pane_content[2], FALSE, FALSE);
+ split_top_left = FALSE;
break;
case(layout_type_3):
main_first_pane = main_pane_h1;
main_second_pane = main_pane_v1;
- gtk_paned_add1(GTK_PANED(main_first_pane), main_second_pane);
- gtk_paned_add2(GTK_PANED(main_first_pane), pane_content[2]);
- gtk_paned_pack1(GTK_PANED(main_second_pane), pane_content[0], TRUE, TRUE);
- gtk_paned_pack2(GTK_PANED(main_second_pane), pane_content[1], FALSE, FALSE);
+ split_top_left = TRUE;
break;
case(layout_type_6):
main_first_pane = main_pane_h1;
main_second_pane = main_pane_h2;
- gtk_paned_add1(GTK_PANED(main_first_pane), pane_content[0]);
- gtk_paned_add2(GTK_PANED(main_first_pane), main_second_pane);
- gtk_paned_pack1(GTK_PANED(main_second_pane), pane_content[1], TRUE, TRUE);
- gtk_paned_pack2(GTK_PANED(main_second_pane), pane_content[2], FALSE, FALSE);
+ split_top_left = FALSE;
break;
default:
+ main_first_pane = NULL;
+ main_second_pane = NULL;
+ split_top_left = FALSE;
g_assert_not_reached();
}
+ if (split_top_left) {
+ first_pane_widget1 = main_second_pane;
+ second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
+ second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_2);
+ first_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
+ } else {
+ first_pane_widget1 = main_widget_layout(prefs.gui_layout_content_1);
+ first_pane_widget2 = main_second_pane;
+ second_pane_widget1 = main_widget_layout(prefs.gui_layout_content_2);
+ second_pane_widget2 = main_widget_layout(prefs.gui_layout_content_3);
+ }
+ if (first_pane_widget1 != NULL)
+ gtk_paned_add1(GTK_PANED(main_first_pane), first_pane_widget1);
+ if (first_pane_widget2 != NULL)
+ gtk_paned_add2(GTK_PANED(main_first_pane), first_pane_widget2);
+ if (second_pane_widget1 != NULL)
+ gtk_paned_pack1(GTK_PANED(main_second_pane), second_pane_widget1, TRUE, TRUE);
+ if (second_pane_widget2 != NULL)
+ gtk_paned_pack2(GTK_PANED(main_second_pane), second_pane_widget2, FALSE, FALSE);
gtk_container_add(GTK_CONTAINER(main_vbox), main_first_pane);
+ /* welcome pane */
+ gtk_box_pack_start(GTK_BOX(main_vbox), welcome_pane, TRUE, TRUE, 0);
+
/* statusbar hbox */
gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
}
}
+
+#if 0
+/* XXX - There seems to be some disagreement about if and how this feature should be implemented.
+ As I currently don't have the time to continue this, it's temporarily disabled. - ULFL */
+GtkWidget *
+welcome_item(gchar *stock_item, gchar * label, gchar * message, GtkSignalFunc callback, void *callback_data)
+{
+ GtkWidget *w, *item_hb;
+#if GTK_MAJOR_VERSION >= 2
+ gchar *formatted_message;
+#endif
+
+
+ item_hb = gtk_hbox_new(FALSE, 1);
+
+ w = BUTTON_NEW_FROM_STOCK(stock_item);
+ WIDGET_SET_SIZE(w, 60, 60);
+#if GTK_MAJOR_VERSION >= 2
+ gtk_button_set_label(GTK_BUTTON(w), label);
+#endif
+ gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 0);
+ SIGNAL_CONNECT(w, "clicked", callback, callback_data);
+
+ w = gtk_label_new(message);
+ gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
+#if GTK_MAJOR_VERSION >= 2
+ formatted_message = g_strdup_printf("<span weight=\"bold\" size=\"x-large\">%s</span>", message);
+ gtk_label_set_markup(GTK_LABEL(w), formatted_message);
+ g_free(formatted_message);
+#endif
+
+ gtk_box_pack_start(GTK_BOX(item_hb), w, FALSE, FALSE, 10);
+
+ return item_hb;
+}
+
+
+/* XXX - the layout has to be improved */
+GtkWidget *
+welcome_new(void)
+{
+ GtkWidget *welcome_scrollw, *welcome_hb, *welcome_vb, *item_hb;
+ GtkWidget *w, *icon;
+ gchar * message;
+
+
+ welcome_scrollw = scrolled_window_new(NULL, NULL);
+
+ welcome_hb = gtk_hbox_new(FALSE, 1);
+ /*gtk_container_border_width(GTK_CONTAINER(welcome_hb), 20);*/
+
+ welcome_vb = gtk_vbox_new(FALSE, 1);
+
+ item_hb = gtk_hbox_new(FALSE, 1);
+
+ icon = xpm_to_widget_from_parent(top_level, eicon3d64_xpm);
+ gtk_box_pack_start(GTK_BOX(item_hb), icon, FALSE, FALSE, 5);
+
+#if GTK_MAJOR_VERSION < 2
+ message = "Welcome to Ethereal!";
+#else
+ message = "<span weight=\"bold\" size=\"25000\">" "Welcome to Ethereal!" "</span>";
+#endif
+ w = gtk_label_new(message);
+#if GTK_MAJOR_VERSION >= 2
+ gtk_label_set_markup(GTK_LABEL(w), message);
+#endif
+ gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(item_hb), w, TRUE, TRUE, 5);
+
+ gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+
+ w = gtk_label_new("What would you like to do?");
+ gtk_box_pack_start(GTK_BOX(welcome_vb), w, FALSE, FALSE, 10);
+ gtk_misc_set_alignment (GTK_MISC(w), 0.0, 0.0);
+
+#ifdef HAVE_LIBPCAP
+ item_hb = welcome_item(ETHEREAL_STOCK_CAPTURE_START,
+ "Capture",
+ "Capture live data from your network",
+ GTK_SIGNAL_FUNC(capture_prep_cb), NULL);
+ gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+#endif
+
+ item_hb = welcome_item(GTK_STOCK_OPEN,
+ "Open",
+ "Open a previously captured file",
+ GTK_SIGNAL_FUNC(file_open_cmd_cb), NULL);
+ gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+
+#if (GLIB_MAJOR_VERSION >= 2)
+ item_hb = welcome_item(GTK_STOCK_HOME,
+ "Home",
+ "Visit the Ethereal homepage",
+ GTK_SIGNAL_FUNC(topic_cb), GINT_TO_POINTER(ONLINEPAGE_HOME));
+ gtk_box_pack_start(GTK_BOX(welcome_vb), item_hb, TRUE, FALSE, 5);
+#endif
+
+ /* the end */
+ w = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(welcome_vb), w, TRUE, TRUE, 0);
+
+ w = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
+
+ gtk_box_pack_start(GTK_BOX(welcome_hb), welcome_vb, TRUE, TRUE, 0);
+
+ w = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(welcome_hb), w, TRUE, TRUE, 0);
+
+ gtk_widget_show_all(welcome_hb);
+
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(welcome_scrollw),
+ welcome_hb);
+ gtk_widget_show_all(welcome_scrollw);
+
+ return welcome_scrollw;
+}
+#endif /* 0 */
+
+GtkWidget *
+welcome_new(void)
+{
+ /* this is just a dummy to fill up window space, simply showing nothing */
+ return scrolled_window_new(NULL, NULL);
+}
+
+
+
/*
* XXX - this doesn't appear to work with the paned widgets in
* GTK+ 1.2[.x]; if you hide one of the panes, the splitter remains
gtk_widget_hide(filter_tb);
}
- if (recent.packet_list_show) {
+ if (recent.packet_list_show && have_capture_file) {
gtk_widget_show(pkt_scrollw);
} else {
gtk_widget_hide(pkt_scrollw);
}
- if (recent.tree_view_show) {
+ if (recent.tree_view_show && have_capture_file) {
gtk_widget_show(tv_scrollw);
} else {
gtk_widget_hide(tv_scrollw);
}
- if (recent.byte_view_show) {
+ if (recent.byte_view_show && have_capture_file) {
gtk_widget_show(byte_nb_ptr);
} else {
gtk_widget_hide(byte_nb_ptr);
}
+ if (have_capture_file) {
+ gtk_widget_show(main_first_pane);
+ } else {
+ gtk_widget_hide(main_first_pane);
+ }
+
/*
* Is anything in "main_second_pane" visible?
* If so, show it, otherwise hide it.
} else {
gtk_widget_hide(main_second_pane);
}
+
+ if (!have_capture_file) {
+ if(welcome_pane) {
+ gtk_widget_show(welcome_pane);
+ }
+ } else {
+ gtk_widget_hide(welcome_pane);
+ }
}
#if GTK_MAJOR_VERSION >= 2
/* called, when the window state changes (minimized, maximized, ...) */
static int
-window_state_event_cb (GtkWidget *widget,
+window_state_event_cb (GtkWidget *widget _U_,
GdkEvent *event,
- gpointer data)
+ gpointer data _U_)
{
GdkWindowState new_window_state = ((GdkEventWindowState*)event)->new_window_state;
GList *filter_list = NULL;
GtkTooltips *tooltips;
GtkAccelGroup *accel;
+ gchar *title;
/* Display filter construct dialog has an Apply button, and "OK" not
only sets our text widget, it activates it (i.e., it causes us to
filter the capture). */
TRUE
};
+ /* use user-defined title if preference is set */
+ title = create_user_window_title("The Ethereal Network Analyzer");
+
/* Main window */
- top_level = window_new(GTK_WINDOW_TOPLEVEL, "The Ethereal Network Analyzer");
+ top_level = window_new(GTK_WINDOW_TOPLEVEL, title);
+ g_free(title);
tooltips = gtk_tooltips_new();
-#ifdef WIN32
+#ifdef _WIN32
#if GTK_MAJOR_VERSION < 2
- set_app_font_gtk1(top_level);
+ /* has to be done, after top_level window is created */
+ app_font_gtk1_init(top_level);
#endif
#endif
gtk_widget_show(pkt_scrollw);
/* Tree view */
-#if GTK_MAJOR_VERSION < 2
- item_style = gtk_style_new();
- gdk_font_unref(item_style->font);
- item_style->font = m_r_font;
-#endif
tv_scrollw = main_tree_view_new(prefs, &tree_view);
WIDGET_SET_SIZE(tv_scrollw, -1, tv_size);
gtk_widget_show(tv_scrollw);
/* Panes for the packet list, tree, and byte view */
- none_lb = gtk_label_new("None");
-
main_pane_v1 = gtk_vpaned_new();
gtk_widget_show(main_pane_v1);
main_pane_v2 = gtk_vpaned_new();
/* Pane for the statusbar */
status_pane = gtk_hpaned_new();
gtk_widget_show(status_pane);
-}
+ /* Pane for the welcome screen */
+ welcome_pane = welcome_new();
+ gtk_widget_show(welcome_pane);
+}
-void
-set_last_open_dir(char *dirname)
+static void
+show_main_window(gboolean doing_work)
{
- int len;
- gchar *new_last_open_dir;
+ main_set_for_capture_file(doing_work);
- if (dirname) {
- len = strlen(dirname);
- if (dirname[len-1] == G_DIR_SEPARATOR) {
- new_last_open_dir = g_strconcat(dirname, NULL);
- }
- else {
- new_last_open_dir = g_strconcat(dirname,
- G_DIR_SEPARATOR_S, NULL);
- }
+ /*** we have finished all init things, show the main window ***/
+ gtk_widget_show(top_level);
- if (last_open_dir == NULL ||
- strcmp(last_open_dir, new_last_open_dir) != 0)
- updated_last_open_dir = TRUE;
- }
- else {
- new_last_open_dir = NULL;
- if (last_open_dir != NULL)
- updated_last_open_dir = TRUE;
- }
+ /* the window can be maximized only, if it's visible, so do it after show! */
+ main_load_window_geometry(top_level);
- if (last_open_dir) {
- g_free(last_open_dir);
- }
- last_open_dir = new_last_open_dir;
+ /* process all pending GUI events before continue */
+ while (gtk_events_pending()) gtk_main_iteration();
+
+ /* Pop up any queued-up alert boxes. */
+ display_queued_messages();
}