Changes from Graham Bloice to support "Update list of packets in real
[obnox/wireshark/wip.git] / gtk / capture_dlg.c
1 /* capture_dlg.c
2  * Routines for packet capture windows
3  *
4  * $Id: capture_dlg.c,v 1.26 2000/06/15 08:02:42 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #ifdef HAVE_LIBPCAP
32
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <gtk/gtk.h>
37
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #include <time.h>
43
44 #ifdef NEED_SNPRINTF_H
45 # ifdef HAVE_STDARG_H
46 #  include <stdarg.h>
47 # else
48 #  include <varargs.h>
49 # endif
50 # include "snprintf.h"
51 #endif
52
53 #include "capture.h"
54 #include "globals.h"
55 #include "main.h"
56 #include "ui_util.h"
57 #include "capture_dlg.h"
58 #include "filter_prefs.h"
59 #include "simple_dialog.h"
60 #include "dlg_utils.h"
61 #include "util.h"
62
63 /* Capture callback data keys */
64 #define E_CAP_IFACE_KEY       "cap_iface"
65 #define E_CAP_FILT_KEY        "cap_filter_te"
66 #define E_CAP_FILE_TE_KEY     "cap_file_te"
67 #define E_CAP_COUNT_KEY       "cap_count"
68 #define E_CAP_SNAP_KEY        "cap_snap"
69 #define E_CAP_SYNC_KEY        "cap_sync"
70 #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll"
71 #define E_CAP_RESOLVE_KEY     "cap_resolve"
72
73 #define E_FS_CALLER_PTR_KEY       "fs_caller_ptr"
74 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
75
76 static void
77 capture_prep_file_cb(GtkWidget *w, gpointer te);
78
79 static void
80 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data);
81
82 static void
83 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data);
84
85 static void
86 cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data);
87
88 static void
89 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
90
91 static void
92 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w);
93
94 static void
95 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data);
96
97 /*
98  * Keep a static pointer to the current "Capture Preferences" window, if
99  * any, so that if somebody tries to do "Capture:Start" while there's
100  * already a "Capture Preferences" window up, we just pop up the existing
101  * one, rather than creating a new one.
102  */
103 static GtkWidget *cap_open_w;
104
105 void
106 capture_prep_cb(GtkWidget *w, gpointer d)
107 {
108   GtkWidget     *if_cb, *if_lb,
109                 *count_lb, *count_cb, *main_vb, *if_hb, *count_hb,
110                 *filter_hb, *filter_bt, *filter_te,
111                 *file_hb, *file_bt, *file_te,
112                 *caplen_hb,
113                 *bbox, *ok_bt, *cancel_bt, *snap_lb,
114                 *snap_sb, *sync_cb, *auto_scroll_cb, *resolv_cb;
115   GtkAccelGroup *accel_group;
116   GtkAdjustment *adj;
117   GList         *if_list, *count_list = NULL;
118   gchar         *count_item1 = "0 (Infinite)", count_item2[16];
119   int           err;
120   char          err_str[PCAP_ERRBUF_SIZE];
121
122   if (cap_open_w != NULL) {
123     /* There's already a "Capture Preferences" dialog box; reactivate it. */
124     reactivate_window(cap_open_w);
125     return;
126   }
127
128   if_list = get_interface_list(&err, err_str);
129   if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) {
130     simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s",
131                         err_str);
132   }
133   
134   cap_open_w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
135   gtk_window_set_title(GTK_WINDOW(cap_open_w), "Ethereal: Capture Preferences");
136   gtk_signal_connect(GTK_OBJECT(cap_open_w), "destroy",
137         GTK_SIGNAL_FUNC(capture_prep_destroy_cb), NULL);
138
139   /* Accelerator group for the accelerators (or, as they're called in
140      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
141      Ctrl+<key> is an accelerator). */
142   accel_group = gtk_accel_group_new();
143   gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group);
144   
145   /* Container for each row of widgets */
146   main_vb = gtk_vbox_new(FALSE, 3);
147   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
148   gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb);
149   gtk_widget_show(main_vb);
150   
151   /* Interface row */
152   if_hb = gtk_hbox_new(FALSE, 3);
153   gtk_container_add(GTK_CONTAINER(main_vb), if_hb);
154   gtk_widget_show(if_hb);
155   
156   if_lb = gtk_label_new("Interface:");
157   gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 0);
158   gtk_widget_show(if_lb);
159   
160   if_cb = gtk_combo_new();
161   if (if_list != NULL)
162     gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list);
163   if (cf.iface)
164     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cf.iface);
165   else if (if_list)
166     gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data);
167   gtk_box_pack_start(GTK_BOX(if_hb), if_cb, FALSE, FALSE, 0);
168   gtk_widget_show(if_cb);
169   
170   free_interface_list(if_list);
171
172   /* Count row */
173   count_hb = gtk_hbox_new(FALSE, 3);
174   gtk_container_add(GTK_CONTAINER(main_vb), count_hb);
175   gtk_widget_show(count_hb);
176   
177   count_lb = gtk_label_new("Count:");
178   gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0);
179   gtk_widget_show(count_lb);
180   
181   count_list = g_list_append(count_list, count_item1);
182   if (cf.count) {
183     snprintf(count_item2, 15, "%d", cf.count);
184     count_list = g_list_append(count_list, count_item2);
185   }
186
187   count_cb = gtk_combo_new();
188   gtk_combo_set_popdown_strings(GTK_COMBO(count_cb), count_list);
189   gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0);
190   gtk_widget_show(count_cb);
191
192   while (count_list)
193     count_list = g_list_remove_link(count_list, count_list);
194
195   /* Filter row */
196   filter_hb = gtk_hbox_new(FALSE, 3);
197   gtk_container_add(GTK_CONTAINER(main_vb), filter_hb);
198   gtk_widget_show(filter_hb);
199   
200   filter_bt = gtk_button_new_with_label("Filter:");
201   gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
202     GTK_SIGNAL_FUNC(filter_browse_cb), NULL);
203   gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, TRUE, 0);
204   gtk_widget_show(filter_bt);
205   
206   filter_te = gtk_entry_new();
207   if (cf.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cf.cfilter);
208   gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
209   gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 0);
210   gtk_widget_show(filter_te);
211   
212   /* File row */
213   file_hb = gtk_hbox_new(FALSE, 1);
214   gtk_container_add(GTK_CONTAINER(main_vb), file_hb);
215   gtk_widget_show(file_hb);
216   
217   file_bt = gtk_button_new_with_label("File:");
218   gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3);
219   gtk_widget_show(file_bt);
220   
221   file_te = gtk_entry_new();
222   gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3);
223   gtk_widget_show(file_te);
224
225   gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
226     GTK_SIGNAL_FUNC(capture_prep_file_cb), GTK_OBJECT(file_te));
227
228   /* Misc row: Capture file checkbox and snap spinbutton */
229   caplen_hb = gtk_hbox_new(FALSE, 3);
230   gtk_container_add(GTK_CONTAINER(main_vb), caplen_hb);
231   gtk_widget_show(caplen_hb);
232
233   snap_lb = gtk_label_new("Capture length");
234   gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5);
235   gtk_box_pack_start(GTK_BOX(caplen_hb), snap_lb, FALSE, FALSE, 6);
236   gtk_widget_show(snap_lb);
237
238   adj = (GtkAdjustment *) gtk_adjustment_new((float) cf.snap,
239     MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0);
240   snap_sb = gtk_spin_button_new (adj, 0, 0);
241   gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE);
242   gtk_widget_set_usize (snap_sb, 80, 0);
243   gtk_box_pack_start (GTK_BOX(caplen_hb), snap_sb, FALSE, FALSE, 3); 
244   gtk_widget_show(snap_sb);
245   
246   sync_cb = dlg_check_button_new_with_label_with_mnemonic(
247                 "_Update list of packets in real time", accel_group);
248   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), sync_mode);
249   gtk_container_add(GTK_CONTAINER(main_vb), sync_cb);
250   gtk_widget_show(sync_cb);
251
252   auto_scroll_cb = dlg_check_button_new_with_label_with_mnemonic(
253                 "_Automatic scrolling in live capture", accel_group);
254   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), auto_scroll_live);
255   gtk_container_add(GTK_CONTAINER(main_vb), auto_scroll_cb);
256   gtk_widget_show(auto_scroll_cb);
257
258   resolv_cb = dlg_check_button_new_with_label_with_mnemonic(
259                 "Enable _name resolution", accel_group);
260   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(resolv_cb), g_resolving_actif);
261   gtk_container_add(GTK_CONTAINER(main_vb), resolv_cb);
262   gtk_widget_show(resolv_cb);
263   
264   /* Button row: OK and cancel buttons */
265   bbox = gtk_hbutton_box_new();
266   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
267   gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
268   gtk_container_add(GTK_CONTAINER(main_vb), bbox);
269   gtk_widget_show(bbox);
270
271   ok_bt = gtk_button_new_with_label ("OK");
272   gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
273     GTK_SIGNAL_FUNC(capture_prep_ok_cb), GTK_OBJECT(cap_open_w));
274   GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
275   gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
276   gtk_widget_grab_default(ok_bt);
277   gtk_widget_show(ok_bt);
278
279   cancel_bt = gtk_button_new_with_label ("Cancel");
280   gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
281     GTK_SIGNAL_FUNC(capture_prep_close_cb), GTK_OBJECT(cap_open_w));
282   GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
283   gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
284   gtk_widget_show(cancel_bt);
285
286   /* Attach pointers to needed widgets to the capture prefs window/object */
287   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_IFACE_KEY, if_cb);
288   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILT_KEY,  filter_te);
289   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILE_TE_KEY,  file_te);
290   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_KEY, count_cb);
291   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_KEY,  snap_sb);
292   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY,  sync_cb);
293   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb);
294   gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RESOLVE_KEY,  resolv_cb);
295
296   /* Catch the "activate" signal on the frame number and file name text
297      entries, so that if the user types Return there, we act as if the
298      "OK" button had been selected, as happens if Return is typed if some
299      widget that *doesn't* handle the Return key has the input focus. */
300   dlg_set_activate(filter_te, ok_bt);
301   dlg_set_activate(file_te, ok_bt);
302
303   /* Catch the "key_press_event" signal in the window, so that we can catch
304      the ESC key being pressed and act as if the "Cancel" button had
305      been selected. */
306   dlg_set_cancel(cap_open_w, cancel_bt);
307
308   /* XXX - why does not
309
310      gtk_widget_grab_focus(if_cb);
311
312     give the initial focus to the "Interface" combo box?
313
314     Or should I phrase that as "why does GTK+ continually frustrate
315     attempts to make GUIs driveable from the keyboard?"  We have to
316     go catch the activate signal on every single GtkEntry widget
317     (rather than having widgets whose activate signal is *not*
318     caught not catch the Return keystroke, so that it passes on,
319     ultimately, to the window, which can activate the default
320     widget, i.e. the "OK" button); we have to catch the "key_press_event"
321     signal and have the handler check for ESC, so that we can have ESC
322     activate the "Cancel" button; in order to support Alt+<key> mnemonics
323     for buttons and the like, we may have to construct an accelerator
324     group by hand and set up the accelerators by hand (if that even
325     works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()"
326     to keep some container widget from getting the initial focus, so that
327     you don't have to tab into the first widget in order to start typing
328     in it; and it now appears that you simply *can't* make a combo box
329     get the initial focus, at least not in the obvious fashion. Sigh.... */
330
331   gtk_widget_show(cap_open_w);
332 }
333
334 static void
335 capture_prep_file_cb(GtkWidget *w, gpointer file_te)
336 {
337   GtkWidget *caller = gtk_widget_get_toplevel(w);
338   GtkWidget *fs;
339
340   /* Has a file selection dialog box already been opened for that top-level
341      widget? */
342   fs = gtk_object_get_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY);
343
344   if (fs != NULL) {
345     /* Yes.  Just re-activate that dialog box. */
346     reactivate_window(fs);
347     return;
348   }
349
350   fs = gtk_file_selection_new ("Ethereal: Capture File");
351
352   gtk_object_set_data(GTK_OBJECT(fs), E_CAP_FILE_TE_KEY, file_te);
353
354   /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
355   gtk_object_set_data(GTK_OBJECT(fs), E_FS_CALLER_PTR_KEY, caller);
356
357   /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
358   gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, fs);
359
360   /* Call a handler when the file selection box is destroyed, so we can inform
361      our caller, if any, that it's been destroyed. */
362   gtk_signal_connect(GTK_OBJECT(fs), "destroy",
363             GTK_SIGNAL_FUNC(cap_prep_fs_destroy_cb), NULL);
364
365   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
366     "clicked", (GtkSignalFunc) cap_prep_fs_ok_cb, fs);
367
368   /* Connect the cancel_button to destroy the widget */
369   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
370     "clicked", (GtkSignalFunc) cap_prep_fs_cancel_cb, fs);
371
372   /* Catch the "key_press_event" signal in the window, so that we can catch
373      the ESC key being pressed and act as if the "Cancel" button had
374      been selected. */
375   dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
376   
377   gtk_widget_show(fs);
378 }
379
380 static void
381 cap_prep_fs_ok_cb(GtkWidget *w, gpointer data)
382 {
383   gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data),
384       E_CAP_FILE_TE_KEY)),
385       gtk_file_selection_get_filename (GTK_FILE_SELECTION(data)));
386   gtk_widget_destroy(GTK_WIDGET(data));
387 }
388
389 static void
390 cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data)
391 {
392   gtk_widget_destroy(GTK_WIDGET(data));
393 }  
394
395 static void
396 cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data)
397 {
398   GtkWidget *caller;
399
400   /* Get the widget that requested that we be popped up.
401      (It should arrange to destroy us if it's destroyed, so
402      that we don't get a pointer to a non-existent window here.) */
403   caller = gtk_object_get_data(GTK_OBJECT(win), E_FS_CALLER_PTR_KEY);
404
405   /* Tell it we no longer exist. */
406   gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, NULL);
407
408   /* Now nuke this window. */
409   gtk_grab_remove(GTK_WIDGET(win));
410   gtk_widget_destroy(GTK_WIDGET(win));
411 }
412
413 static void
414 capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w) {
415   GtkWidget *if_cb, *filter_te, *file_te, *count_cb, *snap_sb, *sync_cb,
416             *auto_scroll_cb, *resolv_cb;
417   gchar *if_text;
418   gchar *if_name;
419   gchar *filter_text;
420   gchar *save_file;
421
422   if_cb     = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_IFACE_KEY);
423   filter_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILT_KEY);
424   file_te   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILE_TE_KEY);
425   count_cb  = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_KEY);
426   snap_sb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_KEY);
427   sync_cb   = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY);
428   auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY);
429   resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RESOLVE_KEY);
430
431   if_text =
432     g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry)));
433   if_name = strtok(if_text, " \t");
434   if (if_name == NULL) {
435     simple_dialog(ESD_TYPE_WARN, NULL,
436       "You didn't specify an interface on which to capture packets.");
437     g_free(if_name);
438     return;
439   }
440   if (cf.iface)
441     g_free(cf.iface);
442   cf.iface = g_strdup(if_name);
443   g_free(if_text);
444
445   /* XXX - don't try to get clever and set "cf.filter" to NULL if the
446      filter string is empty, as an indication that we don't have a filter
447      and thus don't have to set a filter when capturing - the version of
448      libpcap in Red Hat Linux 6.1, and versions based on later patches
449      in that series, don't bind the AF_PACKET socket to an interface
450      until a filter is set, which means they aren't bound at all if
451      no filter is set, which means no packets arrive as input on that
452      socket, which means Ethereal never sees any packets. */
453   filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te));
454   if (cf.cfilter)
455     g_free(cf.cfilter);
456   g_assert(filter_text != NULL);
457   cf.cfilter = g_strdup(filter_text); 
458
459   save_file = gtk_entry_get_text(GTK_ENTRY(file_te));
460   if (save_file && save_file[0]) {
461     /* User specified a file to which the capture should be written. */
462     save_file = g_strdup(save_file);
463   } else {
464     /* User didn't specify a file; save to a temporary file. */
465     save_file = NULL;
466   }
467
468   cf.count = atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(count_cb)->entry)));
469
470   cf.snap = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb));
471   if (cf.snap < 1)
472     cf.snap = WTAP_MAX_PACKET_SIZE;
473   else if (cf.snap < MIN_PACKET_SIZE)
474     cf.snap = MIN_PACKET_SIZE;
475
476   sync_mode = GTK_TOGGLE_BUTTON (sync_cb)->active;
477
478   auto_scroll_live = GTK_TOGGLE_BUTTON (auto_scroll_cb)->active;
479
480   g_resolving_actif = GTK_TOGGLE_BUTTON (resolv_cb)->active;
481
482   gtk_widget_destroy(GTK_WIDGET(parent_w));
483
484   do_capture(save_file);
485 }
486
487 static void
488 capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w)
489 {
490   gtk_grab_remove(GTK_WIDGET(parent_w));
491   gtk_widget_destroy(GTK_WIDGET(parent_w));
492 }
493
494 static void
495 capture_prep_destroy_cb(GtkWidget *win, gpointer user_data)
496 {
497   GtkWidget *capture_prep_filter_w;
498   GtkWidget *fs;
499
500   /* Is there a filter edit/selection dialog associated with this
501      Capture Preferences dialog? */
502   capture_prep_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY);
503
504   if (capture_prep_filter_w != NULL) {
505     /* Yes.  Destroy it. */
506     gtk_widget_destroy(capture_prep_filter_w);
507   }
508
509   /* Is there a file selection dialog associated with this
510      Print File dialog? */
511   fs = gtk_object_get_data(GTK_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
512
513   if (fs != NULL) {
514     /* Yes.  Destroy it. */
515     gtk_widget_destroy(fs);
516   }
517
518   /* Note that we no longer have a "Capture Preferences" dialog box. */
519   cap_open_w = NULL;
520 }
521
522 #endif /* HAVE_LIBPCAP */