diff --git a/file.c b/file.c index f1595d0737..f9c895e0e7 100644 --- a/file.c +++ b/file.c @@ -1,7 +1,7 @@ /* file.c * File I/O routines * - * $Id: file.c,v 1.196 2000/07/07 23:09:03 guy Exp $ + * $Id: file.c,v 1.197 2000/07/09 03:29:26 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -95,6 +95,9 @@ static guint32 prevsec, prevusec; static void read_packet(capture_file *cf, int offset); +static void rescan_packets(capture_file *cf, const char *action, + gboolean refilter); + static void set_selected_row(int row); static void freeze_clist(capture_file *cf); @@ -589,7 +592,8 @@ apply_color_filter(gpointer filter_arg, gpointer argp) static int add_packet_to_packet_list(frame_data *fdata, capture_file *cf, - union wtap_pseudo_header *pseudo_header, const u_char *buf) + union wtap_pseudo_header *pseudo_header, const u_char *buf, + gboolean refilter) { apply_color_filter_args args; gint i, row; @@ -620,36 +624,56 @@ add_packet_to_packet_list(frame_data *fdata, capture_file *cf, fdata->cinfo->col_data[i][0] = '\0'; } - /* Apply the filters */ - if (cf->dfcode != NULL || filter_list != NULL) { - protocol_tree = proto_tree_create_root(); - dissect_packet(pseudo_header, buf, fdata, protocol_tree); - if (cf->dfcode != NULL) - fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0; - else - fdata->flags.passed_dfilter = 1; + /* If either - /* Apply color filters, if we have any. */ + we have a display filter and are re-applying it; + + we have a list of color filters; + + we have plugins to apply; + + allocate a protocol tree root node, so that we'll construct + a protocol tree against which a filter expression can be + evaluated. */ + if ((cf->dfcode != NULL && refilter) || filter_list != NULL +#ifdef HAVE_PLUGINS + || enabled_plugins_number > 0 +#endif + ) + protocol_tree = proto_tree_create_root(); + + /* Dissect the frame. */ + dissect_packet(pseudo_header, buf, fdata, protocol_tree); + + /* If we have a display filter, apply it if we're refiltering, otherwise + leave the "passed_dfilter" flag alone. + + If we don't have a display filter, set "passed_dfilter" to 1. */ + if (cf->dfcode != NULL) { + if (refilter) { + if (cf->dfcode != NULL) + fdata->flags.passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, buf, fdata->cap_len) ? 1 : 0; + else + fdata->flags.passed_dfilter = 1; + } + } else + fdata->flags.passed_dfilter = 1; + + /* If we have color filters, and the frame is to be displayed, apply + the color filters. */ + if (fdata->flags.passed_dfilter) { if (filter_list != NULL) { args.protocol_tree = protocol_tree; args.pd = buf; args.fdata = fdata; g_slist_foreach(filter_list, apply_color_filter, &args); } + } + + /* There are no more filters to apply, so we don't need any protocol + tree; free it if we created it. */ + if (protocol_tree != NULL) proto_tree_free(protocol_tree); - } - else { -#ifdef HAVE_PLUGINS - if (enabled_plugins_number > 0) - protocol_tree = proto_tree_create_root(); -#endif - dissect_packet(pseudo_header, buf, fdata, protocol_tree); - fdata->flags.passed_dfilter = 1; -#ifdef HAVE_PLUGINS - if (protocol_tree) - proto_tree_free(protocol_tree); -#endif - } if (fdata->flags.passed_dfilter) { /* This frame passed the display filter, so add it to the clist. */ @@ -766,7 +790,7 @@ read_packet(capture_file *cf, int offset) cf->count++; fdata->num = cf->count; - add_packet_to_packet_list(fdata, cf, pseudo_header, buf); + add_packet_to_packet_list(fdata, cf, pseudo_header, buf, TRUE); } else { /* XXX - if we didn't have read filters, or if we could avoid allocating the "frame_data" structure until we knew whether @@ -814,17 +838,31 @@ filter_packets(capture_file *cf, gchar *dftext) dfilter_destroy(cf->dfcode); cf->dfcode = dfcode; - /* Now go through the list of packets we've read from the capture file, - applying the current display filter, and, if the packet passes the - display filter, add it to the summary display, appropriately - colored. (That's how we colorize the display - it's like filtering - the display, only we don't install a new filter.) */ - colorize_packets(cf); + /* Now rescan the packet list, applying the new filter. */ + rescan_packets(cf, "Filtering", TRUE); return 1; } void colorize_packets(capture_file *cf) +{ + rescan_packets(cf, "Colorizing", FALSE); +} + +void +redissect_packets(capture_file *cf) +{ + rescan_packets(cf, "Reprocessing", TRUE); +} + +/* Rescan the list of packets, reconstructing the CList. + + "action" describes why we're doing this; it's used in the progress + dialog box. + + "refilter" is TRUE if we need to re-evaluate the filter expression. */ +static void +rescan_packets(capture_file *cf, const char *action, gboolean refilter) { frame_data *fdata; progdlg_t *progbar; @@ -866,9 +904,9 @@ colorize_packets(capture_file *cf) cf->first_displayed = NULL; cf->last_displayed = NULL; - /* Iterate through the list of packets, calling a routine - to run the filter on the packet, see if it matches, and - put it in the display list if so. */ + /* Iterate through the list of frames. Call a routine for each frame + to check whether it should be displayed and, if so, add it to + the display list. */ firstsec = 0; firstusec = 0; prevsec = 0; @@ -883,7 +921,7 @@ colorize_packets(capture_file *cf) count = 0; stop_flag = FALSE; - progbar = create_progress_dlg("Filtering", "Stop", &stop_flag); + progbar = create_progress_dlg(action, "Stop", &stop_flag); for (fdata = cf->plist; fdata != NULL; fdata = fdata->next) { /* Update the progress bar, but do it only N_PROGBAR_UPDATES times; @@ -923,7 +961,8 @@ colorize_packets(capture_file *cf) wtap_seek_read (cf->wth, fdata->file_off, &cf->pseudo_header, cf->pd, fdata->cap_len); - row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd); + row = add_packet_to_packet_list(fdata, cf, &cf->pseudo_header, cf->pd, + refilter); if (fdata == selected_frame) selected_row = row; } diff --git a/file.h b/file.h index b91cfbba68..72b6c87bd2 100644 --- a/file.h +++ b/file.h @@ -1,7 +1,7 @@ /* file.h * Definitions for file structures and routines * - * $Id: file.h,v 1.70 2000/07/03 08:35:41 guy Exp $ + * $Id: file.h,v 1.71 2000/07/09 03:29:27 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -140,6 +140,7 @@ int save_cap_file(char *, capture_file *, gboolean, guint); int filter_packets(capture_file *cf, gchar *dfilter); void colorize_packets(capture_file *); +void redissect_packets(capture_file *cf); int print_packets(capture_file *cf, print_args_t *print_args); void change_time_formats(capture_file *); gboolean find_packet(capture_file *cf, dfilter *sfcode); diff --git a/gtk/display_opts.c b/gtk/display_opts.c index 8ae7224da3..6f8f398ad8 100644 --- a/gtk/display_opts.c +++ b/gtk/display_opts.c @@ -1,7 +1,7 @@ /* display_opts.c * Routines for packet display windows * - * $Id: display_opts.c,v 1.10 2000/07/05 02:45:39 guy Exp $ + * $Id: display_opts.c,v 1.11 2000/07/09 03:29:40 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -241,6 +241,7 @@ static void get_display_options(GtkWidget *parent_w) { GtkWidget *button; + gboolean bval; button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_DISPLAY_TIME_ABS_KEY); @@ -267,7 +268,20 @@ get_display_options(GtkWidget *parent_w) button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_DISPLAY_IP_DSCP_KEY); - g_ip_dscp_actif = (GTK_TOGGLE_BUTTON (button)->active); + bval = (GTK_TOGGLE_BUTTON (button)->active); + if (g_ip_dscp_actif != bval) { + g_ip_dscp_actif = bval; + + /* XXX - we "know" here that the IP dissector doesn't need to be + notified if this preference changed. + + Ultimately, we should probably remove this item from the + "Display options" dialog box, as it can be changed from the + "IP" tab in the "Preferences" dialog box. */ + + /* Redissect all the packets, and re-evaluate the display filter. */ + redissect_packets(&cfile); + } } static void diff --git a/gtk/main.c b/gtk/main.c index f76a91ecd4..5f4fca2b5d 100644 --- a/gtk/main.c +++ b/gtk/main.c @@ -1,6 +1,6 @@ /* main.c * - * $Id: main.c,v 1.128 2000/07/05 09:41:04 guy Exp $ + * $Id: main.c,v 1.129 2000/07/09 03:29:40 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -1485,6 +1485,11 @@ main(int argc, char *argv[]) } } + /* 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 its preferences have changed. */ + prefs_apply_all(); + #ifndef HAVE_LIBPCAP if (capture_option_specified) fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n"); diff --git a/gtk/prefs_dlg.c b/gtk/prefs_dlg.c index a107816ac5..7af69af96b 100644 --- a/gtk/prefs_dlg.c +++ b/gtk/prefs_dlg.c @@ -1,7 +1,7 @@ /* prefs_dlg.c * Routines for handling preferences * - * $Id: prefs_dlg.c,v 1.14 2000/07/05 09:41:07 guy Exp $ + * $Id: prefs_dlg.c,v 1.15 2000/07/09 03:29:42 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -334,8 +334,11 @@ pref_fetch(pref_t *pref, gpointer user_data) char *str_val; char *p; guint uval; + gboolean bval; GSList *rb_entry; GtkWidget *button; + gint enumval; + gboolean *pref_changed_p = user_data; /* Fetch the value of the preference, and set the appropriate variable to it. */ @@ -348,11 +351,18 @@ pref_fetch(pref_t *pref, gpointer user_data) if (p == value || *p != '\0') return PREFS_SET_SYNTAX_ERR; /* number was bad */ #endif - *pref->varp.uint = uval; + if (*pref->varp.uint != uval) { + *pref_changed_p = TRUE; + *pref->varp.uint = uval; + } break; case PREF_BOOL: - *pref->varp.bool = GTK_TOGGLE_BUTTON(pref->control)->active; + bval = GTK_TOGGLE_BUTTON(pref->control)->active; + if (*pref->varp.bool != bval) { + *pref_changed_p = TRUE; + *pref->varp.bool = bval; + } break; case PREF_ENUM: @@ -377,15 +387,22 @@ pref_fetch(pref_t *pref, gpointer user_data) /* Get the label, and translate it to a value. */ gtk_label_get(GTK_LABEL(label), &label_string); - *pref->varp.enump = find_val_for_string(label_string, + enumval = find_val_for_string(label_string, pref->info.enum_info.enumvals, 1); + if (*pref->varp.enump != enumval) { + *pref_changed_p = TRUE; + *pref->varp.enump = enumval; + } break; case PREF_STRING: str_val = gtk_entry_get_text(GTK_ENTRY(pref->control)); - if (*pref->varp.string != NULL) - g_free(*pref->varp.string); - *pref->varp.string = g_strdup(str_val); + if (*pref->varp.string == NULL || strcmp(*pref->varp.string, str_val) != 0) { + *pref_changed_p = TRUE; + if (*pref->varp.string != NULL) + g_free(*pref->varp.string); + *pref->varp.string = g_strdup(str_val); + } break; } } @@ -393,9 +410,18 @@ pref_fetch(pref_t *pref, gpointer user_data) static void module_prefs_fetch(module_t *module, gpointer user_data) { + gboolean *must_redissect_p = user_data; + /* For all preferences in this module, fetch its value from this - module's notebook page. */ - prefs_pref_foreach(module, pref_fetch, NULL); + module's notebook page. Find out whether any of them changed. */ + module->prefs_changed = FALSE; /* assume none of them changed */ + prefs_pref_foreach(module, pref_fetch, &module->prefs_changed); + + /* If any of them changed, indicate that we must redissect and refilter + the current capture (if we have one), as the preference change + could cause packets to be dissected differently. */ + if (module->prefs_changed) + *must_redissect_p = TRUE; } static void @@ -432,13 +458,21 @@ module_prefs_clean(module_t *module, gpointer user_data) static void prefs_main_ok_cb(GtkWidget *ok_bt, gpointer parent_w) { + gboolean must_redissect = FALSE; + printer_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_PRINT_PAGE_KEY)); column_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_COLUMN_PAGE_KEY)); stream_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_STREAM_PAGE_KEY)); gui_prefs_ok(gtk_object_get_data(GTK_OBJECT(parent_w), E_GUI_PAGE_KEY)); - prefs_module_foreach(module_prefs_fetch, NULL); + prefs_module_foreach(module_prefs_fetch, &must_redissect); + prefs_apply_all(); prefs_module_foreach(module_prefs_clean, NULL); gtk_widget_destroy(GTK_WIDGET(parent_w)); + + if (must_redissect) { + /* Redissect all the packets, and re-evaluate the display filter. */ + redissect_packets(&cfile); + } } static void diff --git a/prefs-int.h b/prefs-int.h index 0e96f5ff39..3df04f88b6 100644 --- a/prefs-int.h +++ b/prefs-int.h @@ -2,7 +2,7 @@ * Definitions for implementation of preference handling routines; * used by "friends" of the preferences type. * - * $Id: prefs-int.h,v 1.1 2000/07/05 09:40:40 guy Exp $ + * $Id: prefs-int.h,v 1.2 2000/07/09 03:29:27 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -33,6 +33,7 @@ struct pref_module { void (*apply_cb)(void); /* routine to call when preferences applied */ GList *prefs; /* list of its preferences */ int numprefs; /* number of preferences */ + gboolean prefs_changed; /* if TRUE, a preference has changed since we last checked */ }; typedef enum { diff --git a/prefs.c b/prefs.c index e4b2e18829..77f99d0494 100644 --- a/prefs.c +++ b/prefs.c @@ -1,7 +1,7 @@ /* prefs.c * Routines for handling preferences * - * $Id: prefs.c,v 1.31 2000/07/05 09:40:41 guy Exp $ + * $Id: prefs.c,v 1.32 2000/07/09 03:29:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -100,6 +100,7 @@ prefs_register_module(const char *name, const char *title, module->apply_cb = apply_cb; module->prefs = NULL; /* no preferences, to start */ module->numprefs = 0; + module->prefs_changed = FALSE; modules = g_list_append(modules, module); @@ -161,11 +162,18 @@ call_apply_cb(gpointer data, gpointer user_data) { module_t *module = data; - (*module->apply_cb)(); + if (module->prefs_changed) { + if (module->apply_cb != NULL) + (*module->apply_cb)(); + module->prefs_changed = FALSE; + } } /* - * Call the "apply" callback function for each module. + * Call the "apply" callback function for each module if any of its + * preferences have changed, and then clear the flag saying its + * preferences have changed, as the module has been notified of that + * fact. */ void prefs_apply_all(void) @@ -714,6 +722,8 @@ set_pref(gchar *pref_name, gchar *value) fmt_data *cfmt; unsigned long int cval; guint uval; + gboolean bval; + gint enum_val; char *p; gchar *dotp; module_t *module; @@ -836,27 +846,41 @@ set_pref(gchar *pref_name, gchar *value) uval = strtoul(value, &p, pref->info.base); if (p == value || *p != '\0') return PREFS_SET_SYNTAX_ERR; /* number was bad */ - *pref->varp.uint = uval; + if (*pref->varp.uint != uval) { + module->prefs_changed = TRUE; + *pref->varp.uint = uval; + } break; case PREF_BOOL: /* XXX - give an error if it's neither "true" nor "false"? */ if (strcasecmp(value, "true") == 0) - *pref->varp.bool = TRUE; + bval = TRUE; else - *pref->varp.bool = FALSE; + bval = FALSE; + if (*pref->varp.bool != bval) { + module->prefs_changed = TRUE; + *pref->varp.bool = bval; + } break; case PREF_ENUM: /* XXX - give an error if it doesn't match? */ - *pref->varp.enump = find_val_for_string(value, + enum_val = find_val_for_string(value, pref->info.enum_info.enumvals, 1); + if (*pref->varp.enump != enum_val) { + module->prefs_changed = TRUE; + *pref->varp.enump = enum_val; + } break; case PREF_STRING: - if (*pref->varp.string != NULL) - g_free(*pref->varp.string); - *pref->varp.string = g_strdup(value); + if (*pref->varp.string == NULL || strcmp(*pref->varp.string, value) != 0) { + module->prefs_changed = TRUE; + if (*pref->varp.string != NULL) + g_free(*pref->varp.string); + *pref->varp.string = g_strdup(value); + } break; } } diff --git a/prefs.h b/prefs.h index ab628c0eb5..c53410ab82 100644 --- a/prefs.h +++ b/prefs.h @@ -1,7 +1,7 @@ /* prefs.h * Definitions for preference handling routines * - * $Id: prefs.h,v 1.16 2000/07/05 09:40:42 guy Exp $ + * $Id: prefs.h,v 1.17 2000/07/09 03:29:28 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -76,7 +76,10 @@ typedef void (*module_cb)(module_t *module, gpointer user_data); void prefs_module_foreach(module_cb callback, gpointer user_data); /* - * Call the "apply" callback function for each module. + * Call the "apply" callback function for each module if any of its + * preferences have changed, and then clear the flag saying its + * preferences have changed, as the module has been notified of that + * fact. */ void prefs_apply_all(void); diff --git a/tethereal.c b/tethereal.c index bc98efed2b..47fa116c2d 100644 --- a/tethereal.c +++ b/tethereal.c @@ -1,6 +1,6 @@ /* tethereal.c * - * $Id: tethereal.c,v 1.34 2000/07/05 09:40:43 guy Exp $ + * $Id: tethereal.c,v 1.35 2000/07/09 03:29:29 guy Exp $ * * Ethereal - Network traffic analyzer * By Gerald Combs @@ -411,6 +411,11 @@ main(int argc, char *argv[]) } } + /* 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 its preferences have changed. */ + prefs_apply_all(); + #ifndef HAVE_LIBPCAP if (capture_option_specified) fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");