aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Lamping <ulf.lamping@web.de>2005-04-29 14:51:52 +0000
committerUlf Lamping <ulf.lamping@web.de>2005-04-29 14:51:52 +0000
commita48744a84b72939fd4958421fee4ae0cb1991ba8 (patch)
tree1870e4883021400841c6895227fca301b063b71a
parent614a46f36e7eeebf45f01441dc139e7e9e78abbb (diff)
add a new feature: list the files of a "File Set" (set of files generated by capturing "Multiple Files"/ringbuffer) and jump from one file of it to the next/previous one
svn path=/trunk/; revision=14231
-rw-r--r--Makefile.common2
-rw-r--r--file.c7
-rw-r--r--fileset.c389
-rw-r--r--fileset.h75
-rw-r--r--gtk/Makefile.am1
-rw-r--r--gtk/Makefile.common1
-rw-r--r--gtk/compat_macros.h16
-rw-r--r--gtk/fileset_dlg.c373
-rw-r--r--gtk/fileset_dlg.h36
-rw-r--r--gtk/help_dlg.c11
-rw-r--r--gtk/help_dlg.h1
-rw-r--r--gtk/menu.c13
-rw-r--r--gtk/menu.h7
13 files changed, 930 insertions, 2 deletions
diff --git a/Makefile.common b/Makefile.common
index a105566ac4..8d679a6bda 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -98,6 +98,7 @@ ETHEREAL_COMMON_INCLUDES = \
conditions.h \
disabled_protos.h \
file.h \
+ fileset.h \
packet-range.h \
pcap-util.h \
pcap-util-int.h \
@@ -159,6 +160,7 @@ ethereal_SOURCES = \
capture_loop.c \
color_filters.c \
file.c \
+ fileset.c \
filters.c \
g711.c \
merge.c \
diff --git a/file.c b/file.c
index dd624f8771..95b276d69b 100644
--- a/file.c
+++ b/file.c
@@ -69,6 +69,7 @@
#include "packet-range.h"
#include "print.h"
#include "file.h"
+#include "fileset.h"
#include "util.h"
#include "merge.h"
#include "alert_box.h"
@@ -177,6 +178,7 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
int fd;
struct stat cf_stat;
+
wth = wtap_open_offline(fname, err, &err_info, TRUE);
if (wth == NULL)
goto fail;
@@ -238,6 +240,8 @@ cf_open(capture_file *cf, const char *fname, gboolean is_tempfile, int *err)
G_ALLOC_AND_FREE);
g_assert(cf->plist_chunk);
+ fileset_file_opened(fname);
+
return CF_OK;
fail:
@@ -245,6 +249,7 @@ fail:
return CF_ERROR;
}
+
/*
* Reset the state for the currently closed file, but don't do the
* UI callbacks; this is for use in "cf_open()", where we don't
@@ -305,6 +310,8 @@ cf_reset_state(capture_file *cf)
/* We have no file open. */
cf->state = FILE_CLOSED;
+
+ fileset_file_closed();
}
/* Reset everything to a pristine state */
diff --git a/fileset.c b/fileset.c
new file mode 100644
index 0000000000..15a8f6703a
--- /dev/null
+++ b/fileset.c
@@ -0,0 +1,389 @@
+/* fileset.c
+ * Routines for handling file sets
+ *
+ * $Id$
+ *
+ * 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_IO_H
+#include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+
+#include <glib.h>
+
+#include "globals.h"
+
+#include <epan/filesystem.h>
+
+#include "fileset.h"
+
+
+
+typedef struct _fileset {
+ GList *entries;
+ const char *dirname;
+} fileset;
+
+/* this is the fileset's global data */
+fileset set = { NULL, NULL};
+
+
+/* is this a probable file of a file set (does the naming pattern match)? */
+gboolean
+fileset_filename_match_pattern(const char *fname)
+{
+ char *pfx;
+ int baselen;
+ int minlen = strlen("_00001_20050418010750");
+ char *filename;
+
+
+ /* d:\dir1\test_00001_20050418010750.cap */
+ filename = g_strdup(get_basename(fname));
+
+ /* test_00001_20050418010750.cap */
+ pfx = strrchr(filename, '.');
+ if(pfx == NULL) {
+ return FALSE;
+ }
+ /* test_00001_20050418010750 */
+ *pfx = '\0';
+
+ /* filename long enough? */
+ baselen = strlen(filename);
+ if(baselen < minlen) {
+ g_free(filename);
+ return FALSE;
+ }
+
+ /* there must be two underscores at special places */
+ if(filename[baselen-minlen] != '_' || filename[baselen-minlen+6] != '_') {
+ g_free(filename);
+ return FALSE;
+ }
+
+ /* replace the two underscores by digits */
+ filename[baselen-minlen] = '0';
+ filename[baselen-minlen+6] = '0';
+
+ /* we should have only digits now */
+ while(minlen--) {
+ baselen--;
+
+ if(!isdigit(filename[baselen])) {
+ g_free(filename);
+ return FALSE;
+ }
+ }
+
+ g_free(filename);
+
+ /* ok, seems to be good */
+ return TRUE;
+}
+
+
+/* test, if both files could be in the same file set */
+gboolean
+fileset_is_file_in_set(const char *fname1, const char *fname2)
+{
+ char *pfx1;
+ char *pfx2;
+ char *dup_f1;
+ char *dup_f2;
+ int minlen = strlen("_00001_20050418010750");
+
+
+ dup_f1 = g_strdup(fname1);
+ dup_f2 = g_strdup(fname2);
+
+ pfx1 = strrchr(dup_f1, '.');
+ pfx2 = strrchr(dup_f2, '.');
+
+ if(strcmp(pfx1, pfx2) != 0) {
+ g_free(dup_f1);
+ g_free(dup_f2);
+ return FALSE;
+ }
+
+ *(pfx1-minlen) = '\0';
+ *(pfx2-minlen) = '\0';
+
+ if(strcmp(dup_f1, dup_f2) != 0) {
+ g_free(dup_f1);
+ g_free(dup_f2);
+ return FALSE;
+ }
+
+ g_free(dup_f1);
+ g_free(dup_f2);
+ return TRUE;
+}
+
+
+/* we know this file is part of the set, so add it */
+fileset_entry *
+fileset_add_file(const char *dirname, const char *fname, gboolean current)
+{
+ int fh, result;
+ struct _stat buf;
+ char *path;
+ fileset_entry *entry = NULL;
+
+
+ path = g_strdup_printf("%s%s", dirname, fname);
+
+ fh = open( path, _O_RDONLY );
+ if(fh != -1) {
+
+ /* Get statistics */
+ result = _fstat( fh, &buf );
+
+ /* Show statistics if they are valid */
+ if( result == 0 ) {
+ entry = g_malloc(sizeof(fileset_entry));
+
+ entry->fullname = g_strdup(path);
+ entry->name = g_strdup(fname);
+ entry->ctime = buf.st_ctime;
+ entry->mtime = buf.st_mtime;
+ entry->size = buf.st_size;
+ entry->current = current;
+
+ set.entries = g_list_append(set.entries, entry);
+ }
+
+ _close(fh);
+ }
+
+ g_free(path);
+
+ return entry;
+}
+
+
+/* compare two list entries by creation date/time */
+gint
+fileset_compare_creation(gconstpointer a, gconstpointer b)
+{
+ const fileset_entry *entry_a = a;
+ const fileset_entry *entry_b = b;
+
+ return entry_a->ctime - entry_b->ctime;
+}
+
+
+/* add all file set entries to the dialog */
+void fileset_update_dlg(void)
+{
+ GList *le;
+
+
+ /* add all entires to the dialog */
+ le = g_list_first(set.entries);
+ while(le) {
+ fileset_dlg_add_file(le->data);
+ le = g_list_next(le);
+ }
+}
+
+
+/* walk through the directory of the loaded file and add every file matching the current file */
+void
+fileset_add_dir(const char *fname)
+{
+#if GLIB_MAJOR_VERSION < 2
+ DIR *dir; /* scanned directory */
+ struct dirent *file; /* current file */
+ gchar *name;
+#else /* GLIB 2 */
+ GDir *dir; /* scanned directory */
+ GError **dummy;
+ const char *name;
+#endif
+ fileset_entry *entry;
+ GString *dirname;
+ gchar *fname_dup;
+
+
+ /* get (convert) directory name, but don't touch the given string */
+ fname_dup = get_dirname(g_strdup(fname));
+ dirname = g_string_new(fname_dup);
+ g_free(fname_dup);
+
+ set.dirname = g_strdup(dirname->str);
+
+ dirname = g_string_append_c(dirname, G_DIR_SEPARATOR);
+
+ dummy = g_malloc(sizeof(GError *));
+ *dummy = NULL;
+
+ /* if the current file can't be part of any fileset, do nothing */
+ if(!fileset_filename_match_pattern(fname)) {
+ entry = fileset_add_file(dirname->str, get_basename(fname), TRUE /* current */);
+ if(entry) {
+ fileset_dlg_add_file(entry);
+ }
+ }
+
+ /* go through the files in the directory and check if it's part of the current file set */
+#if GLIB_MAJOR_VERSION < 2
+ if ((dir = opendir(dirname)) != NULL) {
+ while ((file = readdir(dir)) != NULL) {
+ name = (gchar *)file->d_name;
+#else
+ if ((dir = g_dir_open(dirname->str, 0, dummy)) != NULL) {
+ while ((name = g_dir_read_name(dir)) != NULL) {
+#endif
+ if(fileset_filename_match_pattern(name) && fileset_is_file_in_set(name, get_basename(fname))) {
+ fileset_add_file(dirname->str, name, strcmp(name, get_basename(fname))== 0 /* current */);
+ }
+ }
+ }
+
+ g_free(dummy);
+ g_string_free(dirname, TRUE /* free_segment */);
+
+ /* sort entries by creation time */
+ set.entries = g_list_sort(set.entries, fileset_compare_creation);
+
+ fileset_update_dlg();
+}
+
+
+/* get current directory name */
+const char *
+fileset_get_dirname(void)
+{
+ return set.dirname;
+}
+
+
+/* get the current list entry, or NULL */
+GList *
+fileset_get_current(void)
+{
+ GList *le;
+ fileset_entry *entry;
+
+
+ /* add all entires to the dialog */
+ le = g_list_first(set.entries);
+ while(le) {
+ entry = le->data;
+ if(entry->current) {
+ return le;
+ }
+ le = g_list_next(le);
+ }
+
+ return NULL;
+}
+
+
+/* get the file set entry after the current one, or NULL */
+fileset_entry *
+fileset_get_next(void)
+{
+ GList *le;
+
+
+ le = fileset_get_current();
+ if(le == NULL) {
+ return NULL;
+ }
+
+ le = g_list_next(le);
+ if(le == NULL) {
+ return NULL;
+ }
+
+ return le->data;
+}
+
+
+/* get the file set entry before the current one, or NULL */
+fileset_entry *
+fileset_get_previous(void)
+{
+ GList *le;
+
+
+ le = fileset_get_current();
+ if(le == NULL) {
+ return NULL;
+ }
+
+ le = g_list_previous(le);
+ if(le == NULL) {
+ return NULL;
+ }
+
+ return le->data;
+}
+
+
+/* delete a single entry */
+void fileset_entry_delete(gpointer data, gpointer user_data)
+{
+ fileset_entry *entry = data;
+
+ g_free( (gpointer) entry->fullname);
+ entry->fullname = NULL;
+ g_free( (gpointer) entry->name);
+ entry->name = NULL;
+}
+
+
+/* delete the whole file set */
+void fileset_delete(void)
+{
+ /* free the entry list */
+ if(set.entries) {
+ g_list_foreach(set.entries, fileset_entry_delete, NULL);
+ g_list_free(set.entries);
+ set.entries = NULL;
+ }
+
+ /* free the rest */
+ if(set.dirname) {
+ g_free( (gpointer) set.dirname);
+ set.dirname = NULL;
+ }
+}
+
+
diff --git a/fileset.h b/fileset.h
new file mode 100644
index 0000000000..420a70c0f8
--- /dev/null
+++ b/fileset.h
@@ -0,0 +1,75 @@
+/* fileset.h
+ * Definitions for routines for file sets.
+ *
+ * $Id$
+ *
+ * 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.
+ */
+
+#ifndef __FILESET_H__
+#define __FILESET_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+typedef struct _fileset_entry {
+ const char *fullname; /* File name with path (g_strdup'ed) */
+ const char *name; /* File name without path (g_strdup'ed) */
+ time_t ctime; /* create time */
+ time_t mtime; /* last modified time */
+ long size; /* size of file in bytes */
+ gboolean current; /* is this the currently loaded file? */
+} fileset_entry;
+
+
+/* helper: is this a probable file of a file set (does the naming pattern match)? */
+extern gboolean fileset_filename_match_pattern(const char *fname);
+
+/* helper: test, if both files could be in the same file set */
+extern gboolean fileset_is_file_in_set(const char *fname1, const char *fname2);
+
+extern void fileset_add_dir(const char *fname);
+
+extern void fileset_delete(void);
+
+/* get the current directory name */
+extern const char *fileset_get_dirname(void);
+
+extern fileset_entry *fileset_get_next(void);
+extern fileset_entry *fileset_get_previous(void);
+
+
+
+/* this file is a part of the current file set */
+extern void fileset_dlg_add_file(fileset_entry *entry);
+
+extern void fileset_file_opened(const char *fname);
+
+extern void fileset_file_closed(void);
+
+extern void fileset_update_dlg(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __FILESET_H__ */
+
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 846fd185e9..51cf673da8 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -51,6 +51,7 @@ noinst_HEADERS = \
dfilter_expr_dlg.h \
dlg_utils.h \
file_dlg.h \
+ fileset_dlg.h \
filter_dlg.h \
find_dlg.h \
follow_dlg.h \
diff --git a/gtk/Makefile.common b/gtk/Makefile.common
index 338694b975..4d326eafd3 100644
--- a/gtk/Makefile.common
+++ b/gtk/Makefile.common
@@ -57,6 +57,7 @@ ETHEREAL_GTK_SRC = \
drag_and_drop.c \
ethereal-tap-register.c \
file_dlg.c \
+ fileset_dlg.c \
filter_dlg.c \
find_dlg.c \
follow_dlg.c \
diff --git a/gtk/compat_macros.h b/gtk/compat_macros.h
index ab0aec5d2a..73528d27ad 100644
--- a/gtk/compat_macros.h
+++ b/gtk/compat_macros.h
@@ -248,6 +248,18 @@ dlg_radio_button_new_with_label_with_mnemonic( \
radio_group ? gtk_radio_button_group(GTK_RADIO_BUTTON(radio_group)) : NULL, \
label_text, accel_group)
+/** Create a radio button.
+ *
+ * @param radio_group group the radio buttons (another radio button or NULL for first one)
+ * @param label_text the text to display
+ * @param accel_group accelerator group (GTK1 only)
+ * @return the new radio button
+ */
+#define RADIO_BUTTON_NEW_WITH_LABEL(radio_group, label_text) \
+gtk_radio_button_new_with_label ( \
+ radio_group ? gtk_radio_button_group(GTK_RADIO_BUTTON(radio_group)) : NULL, \
+ label_text)
+
/** Create a toggle button.
*
* @param label_text the text to display
@@ -381,6 +393,10 @@ gtk_check_button_new_with_mnemonic(label_text)
gtk_radio_button_new_with_mnemonic_from_widget( \
radio_group ? GTK_RADIO_BUTTON(radio_group) : NULL, label_text)
+#define RADIO_BUTTON_NEW_WITH_LABEL(radio_group, label_text) \
+gtk_radio_button_new_with_label_from_widget( \
+ radio_group ? GTK_RADIO_BUTTON(radio_group) : NULL, label_text)
+
#define TOGGLE_BUTTON_NEW_WITH_MNEMONIC(label_text, accel_group) \
gtk_toggle_button_new_with_mnemonic(label_text)
diff --git a/gtk/fileset_dlg.c b/gtk/fileset_dlg.c
new file mode 100644
index 0000000000..3cedeacae6
--- /dev/null
+++ b/gtk/fileset_dlg.c
@@ -0,0 +1,373 @@
+/* fileset_dlg.c
+ * Routines for the file set dialog
+ *
+ * $Id$
+ *
+ * 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_IO_H
+#include <io.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+
+#include <gtk/gtk.h>
+
+#include "globals.h"
+
+
+#include "compat_macros.h"
+#include "simple_dialog.h"
+
+#include "ui_util.h"
+#include "dlg_utils.h"
+
+#include "main.h"
+#include "menu.h"
+#include "help_dlg.h"
+
+#include <epan/filesystem.h>
+
+#include "fileset.h"
+#include "fileset_dlg.h"
+
+
+
+/*
+ * Keep a static pointer to the current "File Set" window, if
+ * any, so that if somebody tries to do "File Set" while there's
+ * already a "File Set" window up, we just pop up the existing
+ * one, rather than creating a new one.
+ */
+static GtkWidget *fs_w;
+
+
+
+/* various widget related global data */
+int row;
+GtkWidget *fs_tb;
+GtkTooltips *tooltips;
+GtkWidget *fs_dir_lb;
+GtkWidget *fs_first_rb;
+GtkWidget *fs_tb_vb;
+
+
+
+/* open the file corresponding to the given fileset entry */
+static void
+fs_open_entry(fileset_entry *entry)
+{
+ char *fname;
+ int err;
+
+
+ /* make a copy of the filename (cf_close will indirectly destroy it right now) */
+ fname = g_strdup(entry->fullname);
+
+ /* close the old and open the new file */
+ cf_close(&cfile);
+ if (cf_open(&cfile, fname, FALSE, &err) == CF_OK) {
+ cf_read(&cfile);
+ }
+
+ g_free(fname);
+}
+
+
+/* radio button was pressed/released */
+static void
+fs_rb_cb(GtkWidget *open_bt, gpointer fs_data)
+{
+ fileset_entry *entry = fs_data;
+
+ /* button release should have no effect */
+ if(!gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(open_bt) )) {
+ return;
+ }
+
+ fs_open_entry(entry);
+}
+
+
+/* the window was closed, cleanup things */
+static void
+fs_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
+{
+ /* Note that we no longer have a "File Set" dialog box. */
+ fs_w = NULL;
+}
+
+
+/* this file is a part of the current file set, add it to the dialog */
+void
+fileset_dlg_add_file(fileset_entry *entry) {
+ char *created;
+ char *modified;
+ char *size;
+ struct tm *local;
+ GtkWidget *fs_lb;
+ GtkWidget *fs_rb;
+ gchar *title;
+
+
+ if (fs_w == NULL) {
+ return;
+ }
+
+ local = localtime(&entry->ctime);
+ created = g_strdup_printf("%04u.%02u.%02u %02u:%02u:%02u",
+ local->tm_year+1900, local->tm_mon+1, local->tm_mday,
+ local->tm_hour, local->tm_min, local->tm_sec);
+ local = localtime(&entry->mtime);
+ modified = g_strdup_printf("%04u.%02u.%02u %02u:%02u:%02u",
+ local->tm_year+1900, local->tm_mon+1, local->tm_mday,
+ local->tm_hour, local->tm_min, local->tm_sec);
+ size = g_strdup_printf("%ld Bytes", entry->size);
+
+ fs_rb = RADIO_BUTTON_NEW_WITH_LABEL(fs_first_rb, entry->name);
+ if(row == 1) {
+ fs_first_rb = fs_rb;
+ }
+ if(entry->current) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON (fs_rb), entry->current);
+ }
+ gtk_tooltips_set_tip(tooltips, fs_rb, "Open this capture file", NULL);
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_rb, 0, 1, row, row+1);
+ SIGNAL_CONNECT(fs_rb, "toggled", fs_rb_cb, entry);
+ gtk_widget_show(fs_rb);
+
+ fs_lb = gtk_label_new(created);
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 1, 2, row, row+1);
+ gtk_widget_set_sensitive(fs_lb, entry->current);
+ gtk_widget_show(fs_lb);
+
+ fs_lb = gtk_label_new(modified);
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 2, 3, row, row+1);
+ gtk_widget_set_sensitive(fs_lb, entry->current);
+ gtk_widget_show(fs_lb);
+
+ fs_lb = gtk_label_new(size);
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 3, 4, row, row+1);
+ gtk_widget_set_sensitive(fs_lb, entry->current);
+ gtk_widget_show(fs_lb);
+
+ title = g_strdup_printf("Ethereal: %u File%s in Set", row, plurality(row, "", "s"));
+ gtk_window_set_title(GTK_WINDOW(fs_w), title);
+ g_free(title);
+
+ title = g_strdup_printf("... in directory: %s", fileset_get_dirname());
+ gtk_label_set(GTK_LABEL(fs_dir_lb), title);
+ g_free(title);
+
+ row++;
+
+ gtk_widget_show_all(fs_tb);
+
+ g_free(created);
+ g_free(modified);
+ g_free(size);
+}
+
+
+/* init the fileset table */
+void
+fileset_init_table(GtkWidget *parent)
+{
+ GtkWidget *fs_lb;
+
+
+ fs_tb = gtk_table_new(6,1, FALSE);
+ gtk_table_set_row_spacings(GTK_TABLE(fs_tb), 1);
+ gtk_table_set_col_spacings(GTK_TABLE(fs_tb), 12);
+ gtk_container_add(GTK_CONTAINER(parent), fs_tb);
+
+ row = 0;
+ fs_first_rb = NULL;
+
+ fs_lb = gtk_label_new("Filename");
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 0, 1, row, row+1);
+
+ fs_lb = gtk_label_new("Created");
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 1, 2, row, row+1);
+
+ fs_lb = gtk_label_new("Last Modified");
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 2, 3, row, row+1);
+
+ fs_lb = gtk_label_new("Size");
+ gtk_table_attach_defaults(GTK_TABLE(fs_tb), fs_lb, 3, 4, row, row+1);
+
+ gtk_widget_hide(fs_tb);
+
+ gtk_window_set_title(GTK_WINDOW(fs_w), "Ethereal: 0 Files in Set");
+
+ gtk_label_set(GTK_LABEL(fs_dir_lb), "No capture file loaded!");
+
+ row++;
+}
+
+
+/* open the fileset dialog */
+void
+fileset_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+ GtkWidget *main_vb, *bbox, *close_bt, *help_bt;
+#if GTK_MAJOR_VERSION < 2
+ GtkAccelGroup *accel_group;
+#endif
+
+
+ if (fs_w != NULL) {
+ /* There's already a "File Set" dialog box; reactivate it. */
+ reactivate_window(fs_w);
+ return;
+ }
+
+ fs_w = window_new(GTK_WINDOW_TOPLEVEL, "");
+
+ tooltips = gtk_tooltips_new();
+
+#if GTK_MAJOR_VERSION < 2
+ /* 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(fs_w), accel_group);
+#endif
+
+ main_vb = gtk_vbox_new(FALSE, 5);
+ gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
+ gtk_container_add(GTK_CONTAINER(fs_w), main_vb);
+
+ /* add a dummy container, so we can replace the table later */
+ fs_tb_vb = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(main_vb), fs_tb_vb);
+
+ fs_dir_lb = gtk_label_new("");
+ gtk_container_add(GTK_CONTAINER(main_vb), fs_dir_lb);
+
+ fileset_init_table(fs_tb_vb);
+
+ /* Button row: close button */
+ if(topic_available(HELP_FILESET_DIALOG)) {
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, GTK_STOCK_HELP, NULL);
+ } else {
+ bbox = dlg_button_row_new(GTK_STOCK_CLOSE, NULL);
+ }
+ gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 5);
+
+ close_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CLOSE);
+ window_set_cancel_button(fs_w, close_bt, window_cancel_button_cb);
+ gtk_tooltips_set_tip(tooltips, close_bt, "Close this window.", NULL);
+
+ if(topic_available(HELP_FILESET_DIALOG)) {
+ help_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_HELP);
+ SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_FILESET_DIALOG);
+ }
+
+ gtk_widget_grab_default(close_bt);
+
+ SIGNAL_CONNECT(fs_w, "delete_event", window_delete_event_cb, NULL);
+ SIGNAL_CONNECT(fs_w, "destroy", fs_destroy_cb, NULL);
+
+ /* init the dialog content */
+ fileset_update_dlg();
+
+ gtk_widget_show_all(fs_w);
+ window_present(fs_w);
+}
+
+
+/* open the next file in the file set, or do nothing if already the first file */
+void
+fileset_next_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+ fileset_entry *entry;
+
+ entry = fileset_get_next();
+
+ if(entry) {
+ fs_open_entry(entry);
+ }
+}
+
+
+/* open the previous file in the file set, or do nothing if already the first file */
+void
+fileset_previous_cb(GtkWidget *w _U_, gpointer d _U_)
+{
+ fileset_entry *entry;
+
+ entry = fileset_get_previous();
+
+ if(entry) {
+ fs_open_entry(entry);
+ }
+}
+
+
+/* a new capture file was opened, browse the dir and look for files matching the given file set */
+void
+fileset_file_opened(const char *fname) {
+ fileset_add_dir(fname);
+ if(fs_w) {
+ window_present(fs_w);
+ }
+
+ /* update the menu */
+ set_menus_for_file_set(TRUE /* file_set */,
+ fileset_get_previous() != NULL, fileset_get_next() != NULL );
+}
+
+
+/* the capture file was closed */
+void
+fileset_file_closed(void)
+{
+ if(fs_w) {
+ /* reinit the table, title and alike */
+ gtk_widget_ref(fs_tb_vb);
+ gtk_widget_destroy(fs_tb);
+ fileset_delete();
+ fileset_init_table(fs_tb_vb);
+ window_present(fs_w);
+ } else {
+ fileset_delete();
+ }
+
+ /* update the menu */
+ set_menus_for_file_set(FALSE /* file_set */,
+ fileset_get_previous() != NULL, fileset_get_next() != NULL );
+}
+
diff --git a/gtk/fileset_dlg.h b/gtk/fileset_dlg.h
new file mode 100644
index 0000000000..b0330065d6
--- /dev/null
+++ b/gtk/fileset_dlg.h
@@ -0,0 +1,36 @@
+/* fileset_dlg.h
+ * Definitions for the fileset dialog box
+ *
+ * $Id$
+ *
+ * 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.
+ */
+
+#ifndef __FILESET_DLG_H__
+#define __FILESET_DLG_H__
+
+
+/* start getting stats from all files */
+extern void fileset_cb(GtkWidget *w, gpointer d);
+
+extern void fileset_next_cb(GtkWidget *w, gpointer d);
+
+extern void fileset_previous_cb(GtkWidget *w, gpointer d);
+
+#endif /* fileset_dlg.h */
diff --git a/gtk/help_dlg.c b/gtk/help_dlg.c
index 8327b3a694..74bfcff847 100644
--- a/gtk/help_dlg.c
+++ b/gtk/help_dlg.c
@@ -187,8 +187,15 @@ void help_dialog(void)
gboolean topic_available(topic_action_e action) {
#ifdef ETHEREAL_EUG_DIR
- /* online: we have all pages available */
- return TRUE;
+ /* online: we have almost all pages available */
+ switch(action) {
+ case(HELP_FILESET_DIALOG):
+ /* currently not available */
+ return FALSE;
+ break;
+ default:
+ return TRUE;
+ }
#else
/* offline: we have only some pages available */
switch(action) {
diff --git a/gtk/help_dlg.h b/gtk/help_dlg.h
index b221d1d8ab..38228e5968 100644
--- a/gtk/help_dlg.h
+++ b/gtk/help_dlg.h
@@ -58,6 +58,7 @@ typedef enum {
HELP_COLORING_RULES_DIALOG,
HELP_PRINT_DIALOG,
HELP_FIND_DIALOG,
+ HELP_FILESET_DIALOG,
HELP_GOTO_DIALOG,
HELP_CAPTURE_INTERFACES_DIALOG,
HELP_ENABLED_PROTOCOLS_DIALOG,
diff --git a/gtk/menu.c b/gtk/menu.c
index ba9a601844..0a51768700 100644
--- a/gtk/menu.c
+++ b/gtk/menu.c
@@ -46,6 +46,7 @@
#include "filter_dlg.h"
#include "dlg_utils.h"
#include "file_dlg.h"
+#include "fileset_dlg.h"
#include "find_dlg.h"
#include "goto_dlg.h"
#include "summary_dlg.h"
@@ -179,6 +180,11 @@ static GtkItemFactoryEntry menu_items[] =
ITEM_FACTORY_STOCK_ENTRY("/File/Save _As...", "<shift><control>S", file_save_as_cmd_cb,
0, GTK_STOCK_SAVE_AS),
ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
+ ITEM_FACTORY_ENTRY("/File/File Set", NULL, NULL, 0, "<Branch>", NULL),
+ ITEM_FACTORY_ENTRY("/File/File Set/List Files", NULL, fileset_cb, 0, NULL, NULL),
+ ITEM_FACTORY_ENTRY("/File/File Set/Next File", NULL, fileset_next_cb, 0, NULL, NULL),
+ ITEM_FACTORY_ENTRY("/File/File Set/Previous File", NULL, fileset_previous_cb, 0, NULL, NULL),
+ ITEM_FACTORY_ENTRY("/File/<separator>", NULL, NULL, 0, "<Separator>", NULL),
ITEM_FACTORY_ENTRY("/File/_Export", NULL, NULL, 0, "<Branch>", NULL),
ITEM_FACTORY_ENTRY("/File/Export/as \"Plain _Text\" file...", NULL, export_text_cmd_cb,
0, NULL, NULL),
@@ -1974,3 +1980,10 @@ void set_menus_for_packet_history(gboolean back_history, gboolean forward_histor
set_toolbar_for_packet_history(back_history, forward_history);
}
+
+void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file) {
+
+ set_menu_sensitivity(main_menu_factory, "/File/File Set/List Files", file_set);
+ set_menu_sensitivity(main_menu_factory, "/File/File Set/Previous File", previous_file);
+ set_menu_sensitivity(main_menu_factory, "/File/File Set/Next File", next_file);
+}
diff --git a/gtk/menu.h b/gtk/menu.h
index c07b61b305..de917f89a1 100644
--- a/gtk/menu.h
+++ b/gtk/menu.h
@@ -89,6 +89,13 @@ extern gint popup_menu_handler(GtkWidget *widget, GdkEvent *event, gpointer data
*/
extern void set_menus_for_packet_history(gboolean back_history, gboolean forward_history);
+/** The current file has changed, we need to update the file set menu items.
+ *
+ * @param back_history some back history entries available
+ * @param forward_history some forward history entries available
+ */
+extern void set_menus_for_file_set(gboolean file_set, gboolean previous_file, gboolean next_file);
+
/** The popup menu. */
extern GtkWidget *popup_menu_object;