aboutsummaryrefslogtreecommitdiffstats
path: root/gtk2/file_dlg.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk2/file_dlg.c')
-rw-r--r--gtk2/file_dlg.c647
1 files changed, 647 insertions, 0 deletions
diff --git a/gtk2/file_dlg.c b/gtk2/file_dlg.c
new file mode 100644
index 0000000000..97b4ec8b20
--- /dev/null
+++ b/gtk2/file_dlg.c
@@ -0,0 +1,647 @@
+/* file_dlg.c
+ * Dialog boxes for handling files
+ *
+ * $Id: file_dlg.c,v 1.1 2002/08/31 09:55:21 oabad Exp $
+ *
+ * Ethereal - Network traffic analyzer
+ * By Gerald Combs <gerald@ethereal.com>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_DIRECT_H
+#include <direct.h>
+#endif
+
+#include <string.h>
+
+#include <glib.h>
+
+#include <epan/filesystem.h>
+
+#include "globals.h"
+#include "gtkglobals.h"
+#include <epan/resolv.h>
+#include "keys.h"
+#include "filter_prefs.h"
+#include "ui_util.h"
+#include "simple_dialog.h"
+#include "menu.h"
+#include "file_dlg.h"
+#include "dlg_utils.h"
+#include "main.h"
+
+static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
+static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
+static void select_file_type_cb(GtkWidget *w, gpointer data);
+static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
+static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
+
+#define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
+#define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
+#define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
+
+/*
+ * Keep a static pointer to the current "Open Capture File" window, if
+ * any, so that if somebody tries to do "File:Open" while there's already
+ * an "Open Capture File" window up, we just pop up the existing one,
+ * rather than creating a new one.
+ */
+static GtkWidget *file_open_w;
+
+/* Open a file */
+void
+file_open_cmd_cb(GtkWidget *w, gpointer data _U_)
+{
+ GtkWidget *main_vb, *filter_hbox, *filter_bt, *filter_te,
+ *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
+ GtkAccelGroup *accel_group;
+ /* No Apply button, and "OK" just sets our text widget, it doesn't
+ activate it (i.e., it doesn't cause us to try to open the file). */
+ static construct_args_t args = {
+ "Ethereal: Read Filter",
+ FALSE,
+ FALSE
+ };
+
+ if (file_open_w != NULL) {
+ /* There's already an "Open Capture File" dialog box; reactivate it. */
+ reactivate_window(file_open_w);
+ return;
+ }
+
+ file_open_w = gtk_file_selection_new ("Ethereal: Open Capture File");
+ g_signal_connect(G_OBJECT(file_open_w), "destroy",
+ G_CALLBACK(file_open_destroy_cb), NULL);
+
+ /* Accelerator group for the accelerators (or, as they're called in
+ Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
+ Ctrl+<key> is an accelerator). */
+ accel_group = gtk_accel_group_new();
+ gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
+
+ /* If we've opened a file, start out by showing the files in the directory
+ in which that file resided. */
+ if (last_open_dir)
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w), last_open_dir);
+
+ /* Container for each row of widgets */
+ main_vb = gtk_vbox_new(FALSE, 3);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+ gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_open_w)->action_area),
+ main_vb, FALSE, FALSE, 0);
+ gtk_widget_show(main_vb);
+
+ filter_hbox = gtk_hbox_new(FALSE, 1);
+ gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
+ gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
+ gtk_widget_show(filter_hbox);
+
+ filter_bt = gtk_button_new_with_label("Filter:");
+ g_signal_connect(G_OBJECT(filter_bt), "clicked",
+ G_CALLBACK(display_filter_construct_cb), &args);
+ gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
+ gtk_widget_show(filter_bt);
+
+ filter_te = gtk_entry_new();
+ gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
+ gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
+ gtk_widget_show(filter_te);
+
+ gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
+ E_RFILTER_TE_KEY, filter_te);
+
+ m_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "Enable _MAC name resolution", accel_group);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(m_resolv_cb),
+ g_resolv_flags & RESOLV_MAC);
+ gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
+ gtk_widget_show(m_resolv_cb);
+ gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
+ E_FILE_M_RESOLVE_KEY, m_resolv_cb);
+
+ n_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "Enable _network name resolution", accel_group);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(n_resolv_cb),
+ g_resolv_flags & RESOLV_NETWORK);
+ gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
+ gtk_widget_show(n_resolv_cb);
+ gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
+ E_FILE_N_RESOLVE_KEY, n_resolv_cb);
+
+ t_resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
+ "Enable _transport name resolution", accel_group);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(t_resolv_cb),
+ g_resolv_flags & RESOLV_TRANSPORT);
+ gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
+ gtk_widget_show(t_resolv_cb);
+ gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
+ E_FILE_T_RESOLVE_KEY, t_resolv_cb);
+
+ /* Connect the ok_button to file_open_ok_cb function and pass along a
+ pointer to the file selection box widget */
+ g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
+ "clicked", G_CALLBACK(file_open_ok_cb), file_open_w);
+
+ gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
+ E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
+
+ /* Connect the cancel_button to destroy the widget */
+ gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button),
+ "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
+ GTK_OBJECT(file_open_w));
+
+ /* 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(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
+
+ gtk_widget_show(file_open_w);
+}
+
+static void
+file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
+ gchar *cf_name, *s;
+ GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
+ dfilter_t *rfcode = NULL;
+ int err;
+ const gchar *rfilter;
+
+ cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
+ filter_te = gtk_object_get_data(GTK_OBJECT(w), E_RFILTER_TE_KEY);
+ rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
+ if (!dfilter_compile(rfilter, &rfcode)) {
+ simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
+ return;
+ }
+
+ /* Perhaps the user specified a directory instead of a file.
+ Check whether they did. */
+ if (test_for_directory(cf_name) == EISDIR) {
+ /* It's a directory - set the file selection box to display that
+ directory, don't try to open the directory as a capture file. */
+ set_last_open_dir(cf_name);
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
+ return;
+ }
+
+ /* Try to open the capture file. */
+ if ((err = open_cap_file(cf_name, FALSE, &cfile)) != 0) {
+ /* We couldn't open it; don't dismiss the open dialog box,
+ just leave it around so that the user can, after they
+ dismiss the alert box popped up for the open error,
+ try again. */
+ if (rfcode != NULL)
+ dfilter_free(rfcode);
+ g_free(cf_name);
+ return;
+ }
+
+ /* Attach the new read filter to "cf" ("open_cap_file()" succeeded, so
+ it closed the previous capture file, and thus destroyed any
+ previous read filter attached to "cf"). */
+ cfile.rfcode = rfcode;
+
+ /* Set the global resolving variable */
+ g_resolv_flags = 0;
+ m_resolv_cb = gtk_object_get_data(GTK_OBJECT(w), E_FILE_M_RESOLVE_KEY);
+ g_resolv_flags |= GTK_TOGGLE_BUTTON (m_resolv_cb)->active ? RESOLV_MAC : RESOLV_NONE;
+ n_resolv_cb = gtk_object_get_data(GTK_OBJECT(w), E_FILE_N_RESOLVE_KEY);
+ g_resolv_flags |= GTK_TOGGLE_BUTTON (n_resolv_cb)->active ? RESOLV_NETWORK : RESOLV_NONE;
+ t_resolv_cb = gtk_object_get_data(GTK_OBJECT(w), E_FILE_T_RESOLVE_KEY);
+ g_resolv_flags |= GTK_TOGGLE_BUTTON (t_resolv_cb)->active ? RESOLV_TRANSPORT : RESOLV_NONE;
+
+ /* We've crossed the Rubicon; get rid of the file selection box. */
+ gtk_widget_hide(GTK_WIDGET (fs));
+ gtk_widget_destroy(GTK_WIDGET (fs));
+
+ switch (read_cap_file(&cfile, &err)) {
+
+ 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 READ_ABORTED:
+ /* The user bailed out of re-reading the capture file; the
+ capture file has been closed - just free the capture file name
+ string and return (without changing the last containing
+ directory). */
+ g_free(cf_name);
+ return;
+ }
+
+ /* 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);
+ set_last_open_dir(s);
+
+ g_free(cf_name);
+}
+
+static void
+file_open_destroy_cb(GtkWidget *win, gpointer user_data _U_)
+{
+ GtkWidget *file_open_filter_w;
+
+ /* Is there a filter edit/selection dialog associated with this
+ Open Capture File dialog? */
+ file_open_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY);
+
+ if (file_open_filter_w != NULL) {
+ /* Yes. Destroy it. */
+ gtk_widget_destroy(file_open_filter_w);
+ }
+
+ /* Note that we no longer have a "Open Capture File" dialog box. */
+ file_open_w = NULL;
+}
+
+/* Close a file */
+void
+file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
+ close_cap_file(&cfile);
+}
+
+void
+file_save_cmd_cb(GtkWidget *w, gpointer data) {
+ /* If the file's already been saved, do nothing. */
+ if (cfile.user_saved)
+ return;
+
+ /* Do a "Save As". */
+ file_save_as_cmd_cb(w, data);
+}
+
+/* XXX - can we make these not be static? */
+static gboolean filtered;
+static gboolean marked;
+static int filetype;
+static GtkWidget *filter_cb;
+static GtkWidget *mark_cb;
+static GtkWidget *ft_om;
+
+static gboolean
+can_save_with_wiretap(int ft)
+{
+ /* To save a file with Wiretap, Wiretap has to handle that format,
+ and its code to handle that format must be able to write a file
+ with this file's encapsulation type. */
+ return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
+}
+
+/* Generate a list of the file types we can save this file as.
+
+ "filetype" is the type it has now.
+
+ "encap" is the encapsulation for its packets (which could be
+ "unknown" or "per-packet").
+
+ "filtered" is TRUE if we're to save only the packets that passed
+ the display filter (in which case we have to save it using Wiretap)
+ and FALSE if we're to save the entire file (in which case, if we're
+ saving it in the type it has already, we can just copy it).
+
+ "marked" is TRUE if we have to save only the marked packets,
+ the same remark as "filtered" applies.
+*/
+static void
+set_file_type_list(GtkWidget *option_menu)
+{
+ GtkWidget *ft_menu, *ft_menu_item;
+ int ft;
+ guint index;
+ guint item_to_select;
+
+ /* Default to the first supported file type, if the file's current
+ type isn't supported. */
+ item_to_select = 0;
+
+ ft_menu = gtk_menu_new();
+
+ /* Check all file types. */
+ index = 0;
+ for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
+ if (filtered || marked || ft != cfile.cd_t) {
+ /* Filtered, marked or a different file type. We have to use Wiretap. */
+ if (!can_save_with_wiretap(ft))
+ continue; /* We can't. */
+ }
+
+ /* OK, we can write it out in this type. */
+ ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
+ if (ft == filetype) {
+ /* Default to the same format as the file, if it's supported. */
+ item_to_select = index;
+ }
+ g_signal_connect(G_OBJECT(ft_menu_item), "activate",
+ G_CALLBACK(select_file_type_cb), (gpointer)ft);
+ gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
+ gtk_widget_show(ft_menu_item);
+ index++;
+ }
+
+ gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
+}
+
+static void
+select_file_type_cb(GtkWidget *w _U_, gpointer data)
+{
+ int new_filetype = (int)data;
+
+ if (filetype != new_filetype) {
+ /* We can select only the filtered or marked packets to be saved if we can
+ use Wiretap to save the file. */
+ gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(new_filetype));
+ filetype = new_filetype;
+ file_set_save_marked_sensitive();
+ }
+}
+
+static void
+toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
+{
+ gboolean new_filtered;
+
+ new_filtered = GTK_TOGGLE_BUTTON (widget)->active;
+
+ if (filtered != new_filtered) {
+ /* They changed the state of the "filtered" button. */
+ filtered = new_filtered;
+ set_file_type_list(ft_om);
+ }
+}
+
+static void
+toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
+{
+ gboolean new_marked;
+
+ new_marked = GTK_TOGGLE_BUTTON (widget)->active;
+
+ if (marked != new_marked) {
+ /* They changed the state of the "marked" button. */
+ marked = new_marked;
+ set_file_type_list(ft_om);
+ }
+}
+
+/*
+ * Keep a static pointer to the current "Save Capture File As" window, if
+ * any, so that if somebody tries to do "File:Save" or "File:Save As"
+ * while there's already a "Save Capture File As" window up, we just pop
+ * up the existing one, rather than creating a new one.
+ */
+static GtkWidget *file_save_as_w;
+
+void
+file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
+{
+ GtkWidget *ok_bt, *main_vb, *ft_hb, *ft_lb;
+
+ if (file_save_as_w != NULL) {
+ /* There's already an "Save Capture File As" dialog box; reactivate it. */
+ reactivate_window(file_save_as_w);
+ return;
+ }
+
+ /* Default to saving all packets, in the file's current format. */
+ filtered = FALSE;
+ marked = FALSE;
+ filetype = cfile.cd_t;
+
+ file_save_as_w = gtk_file_selection_new ("Ethereal: Save Capture File As");
+ g_signal_connect(G_OBJECT(file_save_as_w), "destroy",
+ G_CALLBACK(file_save_as_destroy_cb), NULL);
+
+ /* If we've opened a file, start out by showing the files in the directory
+ in which that file resided. */
+ if (last_open_dir)
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), last_open_dir);
+
+ /* Connect the ok_button to file_save_as_ok_cb function and pass along a
+ pointer to the file selection box widget */
+ ok_bt = GTK_FILE_SELECTION (file_save_as_w)->ok_button;
+ g_signal_connect(G_OBJECT(ok_bt), "clicked",
+ G_CALLBACK(file_save_as_ok_cb), file_save_as_w);
+
+ /* Container for each row of widgets */
+ main_vb = gtk_vbox_new(FALSE, 3);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+ gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
+ main_vb, FALSE, FALSE, 0);
+ gtk_widget_show(main_vb);
+
+ /*
+ * XXX - should this be sensitive only if the current display filter
+ * has rejected some packets, so that not all packets are currently
+ * being displayed, and if it has accepted some packets, so that some
+ * packets are currently being displayed?
+ *
+ * I'd say "no", as that complicates the UI code, and as one could,
+ * I guess, argue that the user may want to "save all the displayed
+ * packets" even if there aren't any, i.e. save an empty file.
+ */
+ filter_cb = gtk_check_button_new_with_label("Save only packets currently being displayed");
+ gtk_container_add(GTK_CONTAINER(main_vb), filter_cb);
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
+ g_signal_connect(G_OBJECT(filter_cb), "toggled",
+ G_CALLBACK(toggle_filtered_cb), NULL);
+ gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(filetype));
+ gtk_widget_show(filter_cb);
+
+ /*
+ * The argument above could, I guess, be applied to the marked packets,
+ * except that you can't easily tell whether there are any marked
+ * packets, so I could imagine users doing "Save only marked packets"
+ * when there aren't any marked packets, not knowing that they'd
+ * failed to mark them, so I'm more inclined to have the "Save only
+ * marked packets" toggle button enabled only if there are marked
+ * packets to save.
+ */
+ mark_cb = gtk_check_button_new_with_label("Save only marked packets");
+ gtk_container_add(GTK_CONTAINER(main_vb), mark_cb);
+ marked = FALSE;
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), FALSE);
+ g_signal_connect(G_OBJECT(mark_cb), "toggled",
+ G_CALLBACK(toggle_marked_cb), NULL);
+ gtk_widget_show(mark_cb);
+
+ /* File type row */
+ ft_hb = gtk_hbox_new(FALSE, 3);
+ gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
+ gtk_widget_show(ft_hb);
+
+ ft_lb = gtk_label_new("File type:");
+ gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
+ gtk_widget_show(ft_lb);
+
+ ft_om = gtk_option_menu_new();
+
+ /* Generate the list of file types we can save. */
+ set_file_type_list(ft_om);
+ gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
+ gtk_widget_show(ft_om);
+
+ /*
+ * Set the sensitivity of the "Save only marked packets" toggle
+ * button
+ *
+ * This has to be done after we create the file type menu option,
+ * as the routine that sets it also sets that menu.
+ */
+ file_set_save_marked_sensitive();
+
+ /* Connect the cancel_button to destroy the widget */
+ gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button),
+ "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
+ GTK_OBJECT(file_save_as_w));
+
+ /* 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(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
+
+ gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
+
+ gtk_widget_show(file_save_as_w);
+}
+
+/*
+ * Set the "Save only marked packets" toggle button as appropriate for
+ * the current output file type and count of marked packets.
+ *
+ * Called when the "Save As..." dialog box is created and when either
+ * the file type or the marked count changes.
+ */
+void
+file_set_save_marked_sensitive(void)
+{
+ if (file_save_as_w == NULL) {
+ /* We don't currently have a "Save As..." dialog box up. */
+ return;
+ }
+
+ /* We can request that only the marked packets be saved only if we
+ can use Wiretap to save the file and if there *are* marked packets. */
+ if (can_save_with_wiretap(filetype) && cfile.marked_count != 0)
+ gtk_widget_set_sensitive(mark_cb, TRUE);
+ else {
+ /* Force the "Save only marked packets" toggle to "false", turn
+ off the flag it controls, and update the list of types we can
+ save the file as. */
+ marked = FALSE;
+ gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), FALSE);
+ set_file_type_list(ft_om);
+ gtk_widget_set_sensitive(mark_cb, FALSE);
+ }
+}
+
+static void
+file_save_as_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
+ gchar *cf_name;
+
+ cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
+ gtk_widget_hide(GTK_WIDGET (fs));
+ gtk_widget_destroy(GTK_WIDGET (fs));
+
+ /* Write out the packets (all, or only the ones that are currently
+ displayed or marked) to the file with the specified name. */
+ save_cap_file(cf_name, &cfile, filtered, marked, filetype);
+
+ /* If "save_cap_file()" saved the file name we handed it, it saved
+ a copy, so we should free up our copy. */
+ g_free(cf_name);
+}
+
+static void
+file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
+{
+ /* Note that we no longer have a "Save Capture File As" dialog box. */
+ file_save_as_w = NULL;
+}
+
+/* Reload a file using the current read and display filters */
+void
+file_reload_cmd_cb(GtkWidget *w, gpointer data _U_) {
+ /*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
+ GtkWidget *filter_te;
+ gchar *filename;
+ gboolean is_tempfile;
+ int err;
+
+ filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
+
+ if (cfile.dfilter)
+ g_free(cfile.dfilter);
+ cfile.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
+
+ /* If the file could be opened, "open_cap_file()" calls "close_cap_file()"
+ to get rid of state for the old capture file before filling in state
+ for the new capture file. "close_cap_file()" will remove the file if
+ it's a temporary file; we don't want that to happen (for one thing,
+ it'd prevent subsequent reopens from working). Remember whether it's
+ a temporary file, mark it as not being a temporary file, and then
+ reopen it as the type of file it was.
+
+ Also, "close_cap_file()" will free "cfile.filename", so we must make
+ a copy of it first. */
+ filename = g_strdup(cfile.filename);
+ is_tempfile = cfile.is_tempfile;
+ cfile.is_tempfile = FALSE;
+ if (open_cap_file(filename, is_tempfile, &cfile) == 0) {
+ switch (read_cap_file(&cfile, &err)) {
+
+ 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 READ_ABORTED:
+ /* The user bailed out of re-reading the capture file; the
+ capture file has been closed - just free the capture file name
+ string and return (without changing the last containing
+ directory). */
+ g_free(filename);
+ return;
+ }
+ } else {
+ /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
+ Instead, the file was left open, so we should restore "cfile.is_tempfile"
+ ourselves.
+
+ XXX - change the menu? Presumably "open_cap_file()" will do that;
+ make sure it does! */
+ cfile.is_tempfile = is_tempfile;
+ }
+ /* "open_cap_file()" made a copy of the file name we handed it, so
+ we should free up our copy. */
+ g_free(filename);
+}