/* main.c
*
- * $Id: main.c,v 1.318 2003/09/24 02:36:34 guy Exp $
+ * $Id: main.c,v 1.336 2003/12/03 09:28:24 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
#include "register.h"
#include "ringbuffer.h"
#include "ui_util.h"
+#include "toolbar.h"
#include "image/clist_ascend.xpm"
#include "image/clist_descend.xpm"
#include "../tap.h"
#include "../util.h"
#include "compat_macros.h"
+#include "find_dlg.h"
#ifdef WIN32
#include "capture-wpcap.h"
static GString *comp_info_str, *runtime_info_str;
gchar *ethereal_path = NULL;
gchar *last_open_dir = NULL;
-gint root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
+static gboolean updated_last_open_dir = FALSE;
+static gint root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
+static gboolean updated_geometry = FALSE;
ts_type timestamp_type = RELATIVE;
GLogLevelFlags log_level, const char *message, gpointer user_data);
#endif
+static gboolean list_link_layer_types;
+
static void create_main_window(gint, gint, gint, e_prefs*);
#define E_DFILTER_CM_KEY "display_filter_combo"
gtk_widget_grab_default(ok_btn);
gtk_widget_show(ok_btn);
+ /* Catch the "key_press_event" signal in the window, so that we can catch
+ the ESC key being pressed and act as if the "Cancel" button had
+ been selected. */
+ dlg_set_cancel(win, ok_btn);
+
gtk_widget_show(win);
}
hfinfo = cfile.finfo_selected->hfinfo;
g_assert(hfinfo);
if (hfinfo->type == FT_FRAMENUM) {
- framenum = fvalue_get_integer(cfile.finfo_selected->value);
+ framenum = fvalue_get_integer(&cfile.finfo_selected->value);
if (framenum != 0)
goto_frame(&cfile, framenum);
}
if (w == NULL || event == NULL)
return FALSE;
- if (event->type == GDK_BUTTON_PRESS &&
+ if (event->type == GDK_BUTTON_PRESS && event_button->button == 2 &&
+ event_button->window == GTK_CLIST(w)->clist_window &&
gtk_clist_get_selection_info(GTK_CLIST(w), event_button->x,
event_button->y, &row, &column)) {
- if (event_button->button == 2)
- {
- frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(w), row);
- set_frame_mark(!fdata->flags.marked, fdata, row);
- return TRUE;
- }
+ frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(w),
+ row);
+ set_frame_mark(!fdata->flags.marked, fdata, row);
+ return TRUE;
}
return FALSE;
}
#endif
-void reftime_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
- if (cfile.current_frame) {
- /* XXX hum, should better have a "cfile->current_row" here ... */
- set_frame_reftime(!cfile.current_frame->flags.ref_time,
- cfile.current_frame,
- gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
- cfile.current_frame));
+/* 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)
+{
+
+ switch(action){
+ case 0: /* toggle ref frame */
+ if (cfile.current_frame) {
+ /* XXX hum, should better have a "cfile->current_row" here ... */
+ set_frame_reftime(!cfile.current_frame->flags.ref_time,
+ cfile.current_frame,
+ gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
+ cfile.current_frame));
+ }
+ break;
+ case 1: /* find next ref frame */
+ find_previous_next_frame_with_filter("frame.ref_time", FALSE);
+ break;
+ case 2: /* find previous ref frame */
+ find_previous_next_frame_with_filter("frame.ref_time", TRUE);
+ break;
}
}
static gboolean
main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
+{
+ /* "do_quit()" indicates whether the main window should be deleted. */
+ return do_quit();
+}
+
+static gboolean
+main_window_configure_event_cb(GtkWidget *widget, GdkEvent *event _U_, gpointer data _U_)
{
gint desk_x, desk_y;
- /* Try to grab our geometry */
- gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
- if (gdk_window_get_deskrelative_origin(top_level->window,
+ /* 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
+
+ XXX - should we get this from the event itself? */
+
+ gdk_window_get_root_origin(widget->window, &root_x, &root_y);
+ if (gdk_window_get_deskrelative_origin(widget->window,
&desk_x, &desk_y)) {
if (desk_x <= root_x && desk_y <= root_y) {
root_x = desk_x;
}
/* XXX - Is this the "approved" method? */
- gdk_window_get_size(top_level->window, &top_width, &top_height);
+ gdk_window_get_size(widget->window, &top_width, &top_height);
- /* "do_quit()" indicates whether the main window should be deleted. */
- return do_quit();
+ updated_geometry = TRUE;
+
+ return FALSE;
}
void
comp_info_str->str, runtime_info_str->str);
}
#ifdef HAVE_LIBPCAP
- fprintf(stderr, "\n%s [ -vh ] [ -klnpQS ] [ -a <capture autostop condition> ] ...\n",
+ fprintf(stderr, "\n%s [ -vh ] [ -klLnpQS ] [ -a <capture autostop condition> ] ...\n",
PACKAGE);
fprintf(stderr, "\t[ -b <number of ringbuffer files>[:<duration>] ]\n");
fprintf(stderr, "\t[ -B <byte view height> ] [ -c <count> ] [ -f <capture filter> ]\n");
fprintf(stderr, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
- fprintf(stderr, "\t[ -w <savefile> ] [ <infile> ]\n");
+ fprintf(stderr, "\t[ -w <savefile> ] [ -y <link type> ] [ -z <statistics string> ]\n");
+ fprintf(stderr, "\t[ <infile> ]\n");
#else
fprintf(stderr, "\n%s [ -vh ] [ -n ] [ -B <byte view height> ] [ -m <medium font> ]\n",
PACKAGE);
fprintf(stderr, "\t[ -N <resolving> ] [ -o <preference setting> ...\n");
fprintf(stderr, "\t[ -P <packet list height> ] [ -r <infile> ] [ -R <read filter> ]\n");
- fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ] [ <infile> ]\n");
+ fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
+ fprintf(stderr, "\t[ -z <statistics string> ] [ <infile> ]\n");
#endif
}
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];
gboolean stats_known;
struct pcap_stat stats;
#if GTK_MAJOR_VERSION < 2
char *bold_font_name;
#endif
- gint desk_x, desk_y;
gboolean prefs_write_needed = FALSE;
ethereal_tap_list *tli = NULL;
gchar *tap_opt = NULL;
-#define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:vz:"
+#define OPTSTRING_INIT "a:b:B:c:f:hi:klLm:nN:o:pP:Qr:R:Ss:t:T:w:vy:z:"
#ifdef HAVE_LIBPCAP
#ifdef WIN32
capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
capture_opts.has_ring_duration = FALSE;
capture_opts.ringbuffer_duration = 1;
+ capture_opts.linktype = -1;
/* If this is a capture child process, it should pay no attention
to the "prefs.capture_prom_mode" setting in the preferences file;
#else
capture_option_specified = TRUE;
arg_error = TRUE;
+#endif
+ break;
+ case 'L': /* Print list of link-layer types and exit */
+#ifdef HAVE_LIBPCAP
+ list_link_layer_types = TRUE;
+ break;
+#else
+ capture_option_specified = TRUE;
+ arg_error = TRUE;
#endif
break;
case 'm': /* Fixed-width font for the display */
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.
fprintf(stderr, "Invalid argument: %s\n", argv[0]);
arg_error = TRUE;
}
+
+#ifndef HAVE_LIBPCAP
+ 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 (capture_opts.ringbuffer_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 -
- 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) {
- fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
- capture_opts.ringbuffer_on = FALSE;
- }
- 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.ringbuffer_on = FALSE;
- }
- if (!capture_opts.has_autostop_filesize) {
- fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
- capture_opts.ringbuffer_on = FALSE;
- }
- }
-#endif
-
- /* Notify all registered modules that have had any of their preferences
- changed either from one of the preferences file or from the command
- line that their preferences have changed. */
- prefs_apply_all();
-
- /* disabled protocols as per configuration file */
- if (dp_path == NULL) {
- set_disabled_protos_list();
+ if (start_capture && list_link_layer_types) {
+ /* Specifying *both* is bogus. */
+ fprintf(stderr, "ethereal: You cannot specify both -L and a live capture.\n");
+ exit(1);
}
-#ifndef HAVE_LIBPCAP
- if (capture_option_specified)
- fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
-#endif
-#ifdef HAVE_LIBPCAP
- if (start_capture) {
+ if (list_link_layer_types) {
+ /* We're supposed to list the link-layer types for an interface;
+ 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");
+ exit(1);
+ }
+ /* No - did they specify a ring buffer option? */
+ if (capture_opts.ringbuffer_on) {
+ fprintf(stderr, "ethereal: Ring buffer requested, but a capture is not being done.\n");
+ exit(1);
+ }
+ } else {
/* We're supposed to do a live capture; did the user also specify
a capture file to be read? */
- if (cf_name) {
+ 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");
- exit(2);
+ exit(1);
}
-
- /* No - did the user specify an interface to use? */
+
+ /* No - was the ring buffer option specified and, if so, does it make
+ sense? */
+ if (capture_opts.ringbuffer_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 -
+ 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) {
+ fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
+ capture_opts.ringbuffer_on = FALSE;
+ }
+ 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.ringbuffer_on = FALSE;
+ }
+ if (!capture_opts.has_autostop_filesize) {
+ fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
+ capture_opts.ringbuffer_on = FALSE;
+ }
+ }
+ }
+
+ if (start_capture || list_link_layer_types) {
+ /* Did the user specify an interface to use? */
if (cfile.iface == NULL) {
/* No - is a default specified in the preferences file? */
if (prefs->capture_device != NULL) {
}
}
}
+
if (capture_child) {
if (cfile.save_file_fd == -1) {
/* XXX - send this to the standard output as something our parent
- should put in an error message box? */
+ should put in an error message box? */
fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
exit(1);
}
}
+
+ 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);
+ 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"
+ "Please check to make sure you have sufficient permissions, and that\n"
+ "you have the proper interface or pipe specified.\n", err_str);
+ } else
+ fprintf(stderr, "ethereal: The capture device has no data link types.\n");
+ exit(2);
+ }
+ fprintf(stderr, "Data link types (use option -y to set):\n");
+ for (lt_entry = lt_list; lt_entry != NULL;
+ lt_entry = g_list_next(lt_entry)) {
+ data_link_info = lt_entry->data;
+ fprintf(stderr, " %s", data_link_info->name);
+ if (data_link_info->description != NULL)
+ fprintf(stderr, " (%s)", data_link_info->description);
+ else
+ fprintf(stderr, " (not supported)");
+ putchar('\n');
+ }
+ free_pcap_linktype_list(lt_list);
+ exit(0);
+ }
+
#endif
+ /* Notify all registered modules that have had any of their preferences
+ changed either from one of the preferences file or from the command
+ line that their preferences have changed. */
+ prefs_apply_all();
+
+ /* disabled protocols as per configuration file */
+ if (dp_path == NULL) {
+ set_disabled_protos_list();
+ }
+
/* Build the column format array */
col_setup(&cfile.cinfo, prefs->num_cols);
for (i = 0; i < cfile.cinfo.num_cols; i++) {
cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
}
+ for (i = 0; i < cfile.cinfo.num_cols; i++) {
+ int j;
+
+ for (j = 0; j < NUM_COL_FMTS; j++) {
+ if (!cfile.cinfo.fmt_matx[i][j])
+ continue;
+
+ if (cfile.cinfo.col_first[j] == -1)
+ cfile.cinfo.col_first[j] = i;
+ cfile.cinfo.col_last[j] = i;
+ }
+ }
+
#ifdef HAVE_LIBPCAP
if (capture_opts.has_snaplen) {
if (capture_opts.snaplen < 1)
to a file that our parent will read? */
if (!capture_child) {
#endif
- /* No. Pop up the main window, register menus for taps (which we
- must do after creating the main window, so that we can add
- menu items to the main menu), and read in a capture file if
+ /* 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);
- register_all_tap_menus();
- set_menus_for_capture_file(FALSE);
colors_init();
colfilter_init();
set_menus_for_capture_in_progress(FALSE);
#endif
+ if (!start_capture && (cfile.cfilter == NULL || strlen(cfile.cfilter) == 0)) {
+ if (cfile.cfilter) {
+ g_free(cfile.cfilter);
+ }
+ cfile.cfilter = g_strdup(get_conn_cfilter());
+ }
gtk_main();
- /* Try to save 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/#AEN600 */
-
- /* Re-read our saved preferences. */
- /* XXX - Move all of this into a separate function? */
- prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
- &pf_open_errno, &pf_read_errno, &pf_path);
-
- if (pf_path == NULL) {
- if (prefs->gui_geometry_save_position) {
- if (top_level->window != NULL) {
- gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
- if (gdk_window_get_deskrelative_origin(top_level->window,
- &desk_x, &desk_y)) {
- if (desk_x <= root_x && desk_y <= root_y) {
- root_x = desk_x;
- root_y = desk_y;
+ /* If the last opened directory, or our geometry, has changed, save
+ whatever we're supposed to save. */
+ if (updated_last_open_dir || updated_geometry) {
+ /* Re-read our saved preferences. */
+ prefs = read_prefs(&gpf_open_errno, &gpf_read_errno, &gpf_path,
+ &pf_open_errno, &pf_read_errno, &pf_path);
+ if (pf_path == NULL) {
+ /* We succeeded in reading the preferences. */
+
+ if (updated_last_open_dir) {
+ /* The pathname of the last directory in which we've opened
+ a file has changed. If it changed from what's in the
+ preferences file, and we're supposed to save it, update
+ the preference value and note that we will have to write
+ the preferences out. */
+ if (prefs->gui_fileopen_style == FO_STYLE_LAST_OPENED) {
+ /* Yes, we're supposed to save it.
+ Has a file been opened since Ethereal was started? */
+ if (last_open_dir != NULL) {
+ /* Yes. Is the most recently navigated-to directory
+ different from the saved directory? */
+ if (prefs->gui_fileopen_remembered_dir == NULL ||
+ strcmp(prefs->gui_fileopen_remembered_dir, last_open_dir) != 0) {
+ /* Yes. */
+ prefs->gui_fileopen_remembered_dir = last_open_dir;
+ prefs_write_needed = TRUE;
+ }
}
}
}
- if (prefs->gui_geometry_main_x != root_x) {
- prefs->gui_geometry_main_x = root_x;
- prefs_write_needed = TRUE;
- }
- if (prefs->gui_geometry_main_y != root_y) {
- prefs->gui_geometry_main_y = root_y;
- prefs_write_needed = TRUE;
- }
- }
- if (prefs->gui_geometry_save_size) {
- if (top_level->window != NULL) {
- /* XXX - Is this the "approved" method? */
- gdk_window_get_size(top_level->window, &top_width, &top_height);
- }
- if (prefs->gui_geometry_main_width != top_width) {
- prefs->gui_geometry_main_width = top_width;
- prefs_write_needed = TRUE;
+ if (updated_geometry) {
+ /* We got a geometry update, in the form of a configure_notify
+ event, so the geometry has changed. If it changed from
+ what's in the preferences file, and we're supposed to save
+ the current values of the changed geometry item (position or
+ size), update the preference value and note that we will have
+ to write the preferences out.
+
+ XXX - should GUI stuff such as this be in a separate file? */
+ if (prefs->gui_geometry_save_position) {
+ if (prefs->gui_geometry_main_x != root_x) {
+ prefs->gui_geometry_main_x = root_x;
+ prefs_write_needed = TRUE;
+ }
+ if (prefs->gui_geometry_main_y != root_y) {
+ prefs->gui_geometry_main_y = root_y;
+ prefs_write_needed = TRUE;
+ }
+ }
+
+ if (prefs->gui_geometry_save_size) {
+ if (prefs->gui_geometry_main_width != top_width) {
+ prefs->gui_geometry_main_width = top_width;
+ prefs_write_needed = TRUE;
+ }
+ if (prefs->gui_geometry_main_height != top_height) {
+ prefs->gui_geometry_main_height = top_height;
+ prefs_write_needed = TRUE;
+ }
+ }
}
- if (prefs->gui_geometry_main_height != top_height) {
- prefs->gui_geometry_main_height = top_height;
- prefs_write_needed = TRUE;
+
+ /* Save the preferences if we need to do so.
+
+ XXX - this doesn't save the preferences if you don't have a
+ preferences file. Forcibly writing a preferences file would
+ save the current settings even if you haven't changed them,
+ meaning that if the defaults change it won't affect you.
+ Perhaps we need to keep track of what the *user* has changed,
+ and only write out *those* preferences. */
+ if (prefs_write_needed) {
+ write_prefs(&pf_path);
}
+ } else {
+ /* We failed to read the preferences - silently ignore the
+ error. */
+ g_free(pf_path);
}
-
- if (prefs_write_needed) {
- write_prefs(&pf_path);
- }
- } else {
- /* Ignore errors silently */
- g_free(pf_path);
}
epan_cleanup();
WIDGET_SET_SIZE(top_level, DEF_WIDTH, -1);
}
gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
+ SIGNAL_CONNECT(top_level, "configure_event", main_window_configure_event_cb,
+ NULL);
- /* Container for menu bar, paned windows and progress/info box */
+ /* Container for menu bar, toolbar(s), paned windows and progress/info box */
main_vbox = gtk_vbox_new(FALSE, 1);
gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
gtk_widget_show(menubar);
+ /* Main Toolbar */
+ create_toolbar(main_vbox);
+
/* Panes for the packet list, tree, and byte view */
u_pane = gtk_vpaned_new();
gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
* of any widget that ends up calling a callback which needs
* that text entry pointer */
set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
- set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
set_menu_object_data("/Edit/Filters...", E_FILT_TE_PTR_KEY, filter_te);
set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY,
filter_te);
filter_te);
set_menu_object_data("/Display/Prepare/Or Not Selected", E_DFILTER_TE_KEY,
filter_te);
+ set_toolbar_object_data(E_DFILTER_TE_KEY, filter_te);
OBJECT_SET_DATA(popup_menu_object, E_DFILTER_TE_KEY, filter_te);
OBJECT_SET_DATA(popup_menu_object, E_MPACKET_LIST_KEY, packet_list);
set_last_open_dir(char *dirname)
{
int len;
-
- if (last_open_dir) {
- g_free(last_open_dir);
- }
+ gchar *new_last_open_dir;
if (dirname) {
len = strlen(dirname);
if (dirname[len-1] == G_DIR_SEPARATOR) {
- last_open_dir = g_strconcat(dirname, NULL);
+ new_last_open_dir = g_strconcat(dirname, NULL);
}
else {
- last_open_dir = g_strconcat(dirname, G_DIR_SEPARATOR_S,
- NULL);
+ new_last_open_dir = g_strconcat(dirname,
+ G_DIR_SEPARATOR_S, NULL);
}
+
+ if (last_open_dir == NULL ||
+ strcmp(last_open_dir, new_last_open_dir) != 0)
+ updated_last_open_dir = TRUE;
}
else {
- last_open_dir = NULL;
+ new_last_open_dir = NULL;
+ if (last_open_dir != NULL)
+ updated_last_open_dir = TRUE;
+ }
+
+ if (last_open_dir) {
+ g_free(last_open_dir);
}
+ last_open_dir = new_last_open_dir;
}