bf5bf4ed81876613eae02fae3cc924be48dc2a16
[obnox/wireshark/wip.git] / gtk2 / file_dlg.c
1 /* file_dlg.c
2  * Dialog boxes for handling files
3  *
4  * $Id: file_dlg.c,v 1.3 2002/09/05 18:48:51 jmayer Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <gtk/gtk.h>
30
31 #include <epan/filesystem.h>
32
33 #include "globals.h"
34 #include "gtkglobals.h"
35 #include <epan/resolv.h>
36 #include "keys.h"
37 #include "filter_prefs.h"
38 #include "ui_util.h"
39 #include "simple_dialog.h"
40 #include "menu.h"
41 #include "file_dlg.h"
42 #include "dlg_utils.h"
43 #include "main.h"
44
45 static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
46 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
47 static void select_file_type_cb(GtkWidget *w, gpointer data);
48 static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
49 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
50
51 #define E_FILE_M_RESOLVE_KEY      "file_dlg_mac_resolve_key"
52 #define E_FILE_N_RESOLVE_KEY      "file_dlg_network_resolve_key"
53 #define E_FILE_T_RESOLVE_KEY      "file_dlg_transport_resolve_key"
54
55 /*
56  * Keep a static pointer to the current "Open Capture File" window, if
57  * any, so that if somebody tries to do "File:Open" while there's already
58  * an "Open Capture File" window up, we just pop up the existing one,
59  * rather than creating a new one.
60  */
61 static GtkWidget *file_open_w;
62
63 /* Open a file */
64 void
65 file_open_cmd_cb(GtkWidget *w, gpointer data _U_)
66 {
67   GtkWidget     *main_vb, *filter_hbox, *filter_bt, *filter_te,
68                 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
69   /* No Apply button, and "OK" just sets our text widget, it doesn't
70      activate it (i.e., it doesn't cause us to try to open the file). */
71   static construct_args_t args = {
72         "Ethereal: Read Filter",
73         FALSE,
74         FALSE
75   };
76
77   if (file_open_w != NULL) {
78     /* There's already an "Open Capture File" dialog box; reactivate it. */
79     reactivate_window(file_open_w);
80     return;
81   }
82
83   file_open_w = gtk_file_selection_new ("Ethereal: Open Capture File");
84   g_signal_connect(G_OBJECT(file_open_w), "destroy",
85                    G_CALLBACK(file_open_destroy_cb), NULL);
86
87   /* If we've opened a file, start out by showing the files in the directory
88      in which that file resided. */
89   if (last_open_dir)
90     gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w), last_open_dir);
91
92   /* Container for each row of widgets */
93   main_vb = gtk_vbox_new(FALSE, 3);
94   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
95   gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_open_w)->action_area),
96     main_vb, FALSE, FALSE, 0);
97   gtk_widget_show(main_vb);
98
99   filter_hbox = gtk_hbox_new(FALSE, 1);
100   gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
101   gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
102   gtk_widget_show(filter_hbox);
103
104   filter_bt = gtk_button_new_with_label("Filter:");
105   g_signal_connect(G_OBJECT(filter_bt), "clicked",
106                    G_CALLBACK(display_filter_construct_cb), &args);
107   gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
108   gtk_widget_show(filter_bt);
109
110   filter_te = gtk_entry_new();
111   gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
112   gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
113   gtk_widget_show(filter_te);
114
115   gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
116     E_RFILTER_TE_KEY, filter_te);
117
118   m_resolv_cb = gtk_check_button_new_with_mnemonic(
119                   "Enable _MAC name resolution");
120   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(m_resolv_cb),
121         g_resolv_flags & RESOLV_MAC);
122   gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
123   gtk_widget_show(m_resolv_cb);
124   gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
125                   E_FILE_M_RESOLVE_KEY, m_resolv_cb);
126
127   n_resolv_cb = gtk_check_button_new_with_mnemonic(
128                   "Enable _network name resolution");
129   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(n_resolv_cb),
130         g_resolv_flags & RESOLV_NETWORK);
131   gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
132   gtk_widget_show(n_resolv_cb);
133   gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
134                   E_FILE_N_RESOLVE_KEY, n_resolv_cb);
135
136   t_resolv_cb = gtk_check_button_new_with_mnemonic(
137                   "Enable _transport name resolution");
138   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(t_resolv_cb),
139         g_resolv_flags & RESOLV_TRANSPORT);
140   gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
141   gtk_widget_show(t_resolv_cb);
142   gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
143                   E_FILE_T_RESOLVE_KEY, t_resolv_cb);
144
145   /* Connect the ok_button to file_open_ok_cb function and pass along a
146      pointer to the file selection box widget */
147   g_signal_connect(G_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
148                    "clicked", G_CALLBACK(file_open_ok_cb), file_open_w);
149
150   gtk_object_set_data(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->ok_button),
151       E_DFILTER_TE_KEY, gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY));
152
153   /* Connect the cancel_button to destroy the widget */
154   gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button),
155                             "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
156                             GTK_OBJECT(file_open_w));
157
158   /* Catch the "key_press_event" signal in the window, so that we can catch
159      the ESC key being pressed and act as if the "Cancel" button had
160      been selected. */
161   dlg_set_cancel(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
162
163   gtk_widget_show(file_open_w);
164 }
165
166 static void
167 file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
168   gchar       *cf_name, *s;
169   GtkWidget   *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
170   dfilter_t   *rfcode = NULL;
171   int          err;
172   const gchar *rfilter;
173
174   cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
175   filter_te = gtk_object_get_data(GTK_OBJECT(w), E_RFILTER_TE_KEY);
176   rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
177   if (!dfilter_compile(rfilter, &rfcode)) {
178     simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
179     return;
180   }
181
182   /* Perhaps the user specified a directory instead of a file.
183      Check whether they did. */
184   if (test_for_directory(cf_name) == EISDIR) {
185         /* It's a directory - set the file selection box to display that
186            directory, don't try to open the directory as a capture file. */
187         set_last_open_dir(cf_name);
188         gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
189         return;
190   }
191
192   /* Try to open the capture file. */
193   if ((err = open_cap_file(cf_name, FALSE, &cfile)) != 0) {
194     /* We couldn't open it; don't dismiss the open dialog box,
195        just leave it around so that the user can, after they
196        dismiss the alert box popped up for the open error,
197        try again. */
198     if (rfcode != NULL)
199       dfilter_free(rfcode);
200     g_free(cf_name);
201     return;
202   }
203
204   /* Attach the new read filter to "cf" ("open_cap_file()" succeeded, so
205      it closed the previous capture file, and thus destroyed any
206      previous read filter attached to "cf"). */
207   cfile.rfcode = rfcode;
208
209   /* Set the global resolving variable */
210   g_resolv_flags = 0;
211   m_resolv_cb = gtk_object_get_data(GTK_OBJECT(w), E_FILE_M_RESOLVE_KEY);
212   g_resolv_flags |= GTK_TOGGLE_BUTTON (m_resolv_cb)->active ? RESOLV_MAC : RESOLV_NONE;
213   n_resolv_cb = gtk_object_get_data(GTK_OBJECT(w), E_FILE_N_RESOLVE_KEY);
214   g_resolv_flags |= GTK_TOGGLE_BUTTON (n_resolv_cb)->active ? RESOLV_NETWORK : RESOLV_NONE;
215   t_resolv_cb = gtk_object_get_data(GTK_OBJECT(w), E_FILE_T_RESOLVE_KEY);
216   g_resolv_flags |= GTK_TOGGLE_BUTTON (t_resolv_cb)->active ? RESOLV_TRANSPORT : RESOLV_NONE;
217
218   /* We've crossed the Rubicon; get rid of the file selection box. */
219   gtk_widget_hide(GTK_WIDGET (fs));
220   gtk_widget_destroy(GTK_WIDGET (fs));
221
222   switch (read_cap_file(&cfile, &err)) {
223
224   case READ_SUCCESS:
225   case READ_ERROR:
226     /* Just because we got an error, that doesn't mean we were unable
227        to read any of the file; we handle what we could get from the
228        file. */
229     break;
230
231   case READ_ABORTED:
232     /* The user bailed out of re-reading the capture file; the
233        capture file has been closed - just free the capture file name
234        string and return (without changing the last containing
235        directory). */
236     g_free(cf_name);
237     return;
238   }
239
240   /* Save the name of the containing directory specified in the path name,
241      if any; we can write over cf_name, which is a good thing, given that
242      "get_dirname()" does write over its argument. */
243   s = get_dirname(cf_name);
244   set_last_open_dir(s);
245
246   g_free(cf_name);
247 }
248
249 static void
250 file_open_destroy_cb(GtkWidget *win, gpointer user_data _U_)
251 {
252   GtkWidget *file_open_filter_w;
253
254   /* Is there a filter edit/selection dialog associated with this
255      Open Capture File dialog? */
256   file_open_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY);
257
258   if (file_open_filter_w != NULL) {
259     /* Yes.  Destroy it. */
260     gtk_widget_destroy(file_open_filter_w);
261   }
262
263   /* Note that we no longer have a "Open Capture File" dialog box. */
264   file_open_w = NULL;
265 }
266
267 /* Close a file */
268 void
269 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
270   close_cap_file(&cfile);
271 }
272
273 void
274 file_save_cmd_cb(GtkWidget *w, gpointer data) {
275   /* If the file's already been saved, do nothing.  */
276   if (cfile.user_saved)
277     return;
278
279   /* Do a "Save As". */
280   file_save_as_cmd_cb(w, data);
281 }
282
283 /* XXX - can we make these not be static? */
284 static gboolean filtered;
285 static gboolean marked;
286 static int filetype;
287 static GtkWidget *filter_cb;
288 static GtkWidget *mark_cb;
289 static GtkWidget *ft_om;
290
291 static gboolean
292 can_save_with_wiretap(int ft)
293 {
294   /* To save a file with Wiretap, Wiretap has to handle that format,
295      and its code to handle that format must be able to write a file
296      with this file's encapsulation type. */
297   return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
298 }
299
300 /* Generate a list of the file types we can save this file as.
301
302    "filetype" is the type it has now.
303
304    "encap" is the encapsulation for its packets (which could be
305    "unknown" or "per-packet").
306
307    "filtered" is TRUE if we're to save only the packets that passed
308    the display filter (in which case we have to save it using Wiretap)
309    and FALSE if we're to save the entire file (in which case, if we're
310    saving it in the type it has already, we can just copy it).
311
312    "marked" is TRUE if we have to save only the marked packets,
313    the same remark as "filtered" applies.
314 */
315 static void
316 set_file_type_list(GtkWidget *option_menu)
317 {
318   GtkWidget *ft_menu, *ft_menu_item;
319   int ft;
320   guint index;
321   guint item_to_select;
322
323   /* Default to the first supported file type, if the file's current
324      type isn't supported. */
325   item_to_select = 0;
326
327   ft_menu = gtk_menu_new();
328
329   /* Check all file types. */
330   index = 0;
331   for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
332     if (filtered || marked || ft != cfile.cd_t) {
333       /* Filtered, marked or a different file type.  We have to use Wiretap. */
334       if (!can_save_with_wiretap(ft))
335         continue;       /* We can't. */
336     }
337
338     /* OK, we can write it out in this type. */
339     ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
340     if (ft == filetype) {
341       /* Default to the same format as the file, if it's supported. */
342       item_to_select = index;
343     }
344     g_signal_connect(G_OBJECT(ft_menu_item), "activate",
345                      G_CALLBACK(select_file_type_cb), (gpointer)ft);
346     gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
347     gtk_widget_show(ft_menu_item);
348     index++;
349   }
350
351   gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
352   gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
353 }
354
355 static void
356 select_file_type_cb(GtkWidget *w _U_, gpointer data)
357 {
358   int new_filetype = (int)data;
359
360   if (filetype != new_filetype) {
361     /* We can select only the filtered or marked packets to be saved if we can
362        use Wiretap to save the file. */
363     gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(new_filetype));
364     filetype = new_filetype;
365     file_set_save_marked_sensitive();
366   }
367 }
368
369 static void
370 toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
371 {
372   gboolean new_filtered;
373
374   new_filtered = GTK_TOGGLE_BUTTON (widget)->active;
375
376   if (filtered != new_filtered) {
377     /* They changed the state of the "filtered" button. */
378     filtered = new_filtered;
379     set_file_type_list(ft_om);
380   }
381 }
382
383 static void
384 toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
385 {
386   gboolean new_marked;
387
388   new_marked = GTK_TOGGLE_BUTTON (widget)->active;
389
390   if (marked != new_marked) {
391     /* They changed the state of the "marked" button. */
392     marked = new_marked;
393     set_file_type_list(ft_om);
394   }
395 }
396
397 /*
398  * Keep a static pointer to the current "Save Capture File As" window, if
399  * any, so that if somebody tries to do "File:Save" or "File:Save As"
400  * while there's already a "Save Capture File As" window up, we just pop
401  * up the existing one, rather than creating a new one.
402  */
403 static GtkWidget *file_save_as_w;
404
405 void
406 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
407 {
408   GtkWidget *ok_bt, *main_vb, *ft_hb, *ft_lb;
409
410   if (file_save_as_w != NULL) {
411     /* There's already an "Save Capture File As" dialog box; reactivate it. */
412     reactivate_window(file_save_as_w);
413     return;
414   }
415
416   /* Default to saving all packets, in the file's current format. */
417   filtered = FALSE;
418   marked   = FALSE;
419   filetype = cfile.cd_t;
420
421   file_save_as_w = gtk_file_selection_new ("Ethereal: Save Capture File As");
422   g_signal_connect(G_OBJECT(file_save_as_w), "destroy",
423                    G_CALLBACK(file_save_as_destroy_cb), NULL);
424
425   /* If we've opened a file, start out by showing the files in the directory
426      in which that file resided. */
427   if (last_open_dir)
428     gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), last_open_dir);
429
430   /* Connect the ok_button to file_save_as_ok_cb function and pass along a
431      pointer to the file selection box widget */
432   ok_bt = GTK_FILE_SELECTION (file_save_as_w)->ok_button;
433   g_signal_connect(G_OBJECT(ok_bt), "clicked",
434                    G_CALLBACK(file_save_as_ok_cb), file_save_as_w);
435
436   /* Container for each row of widgets */
437   main_vb = gtk_vbox_new(FALSE, 3);
438   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
439   gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
440     main_vb, FALSE, FALSE, 0);
441   gtk_widget_show(main_vb);
442
443   /*
444    * XXX - should this be sensitive only if the current display filter
445    * has rejected some packets, so that not all packets are currently
446    * being displayed, and if it has accepted some packets, so that some
447    * packets are currently being displayed?
448    *
449    * I'd say "no", as that complicates the UI code, and as one could,
450    * I guess, argue that the user may want to "save all the displayed
451    * packets" even if there aren't any, i.e. save an empty file.
452    */
453   filter_cb = gtk_check_button_new_with_label("Save only packets currently being displayed");
454   gtk_container_add(GTK_CONTAINER(main_vb), filter_cb);
455   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filter_cb), FALSE);
456   g_signal_connect(G_OBJECT(filter_cb), "toggled",
457                    G_CALLBACK(toggle_filtered_cb), NULL);
458   gtk_widget_set_sensitive(filter_cb, can_save_with_wiretap(filetype));
459   gtk_widget_show(filter_cb);
460
461   /*
462    * The argument above could, I guess, be applied to the marked packets,
463    * except that you can't easily tell whether there are any marked
464    * packets, so I could imagine users doing "Save only marked packets"
465    * when there aren't any marked packets, not knowing that they'd
466    * failed to mark them, so I'm more inclined to have the "Save only
467    * marked packets" toggle button enabled only if there are marked
468    * packets to save.
469    */
470   mark_cb = gtk_check_button_new_with_label("Save only marked packets");
471   gtk_container_add(GTK_CONTAINER(main_vb), mark_cb);
472   marked = FALSE;
473   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), FALSE);
474   g_signal_connect(G_OBJECT(mark_cb), "toggled",
475                    G_CALLBACK(toggle_marked_cb), NULL);
476   gtk_widget_show(mark_cb);
477
478   /* File type row */
479   ft_hb = gtk_hbox_new(FALSE, 3);
480   gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
481   gtk_widget_show(ft_hb);
482
483   ft_lb = gtk_label_new("File type:");
484   gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
485   gtk_widget_show(ft_lb);
486
487   ft_om = gtk_option_menu_new();
488
489   /* Generate the list of file types we can save. */
490   set_file_type_list(ft_om);
491   gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
492   gtk_widget_show(ft_om);
493
494   /*
495    * Set the sensitivity of the "Save only marked packets" toggle
496    * button
497    *
498    * This has to be done after we create the file type menu option,
499    * as the routine that sets it also sets that menu.
500    */
501   file_set_save_marked_sensitive();
502
503   /* Connect the cancel_button to destroy the widget */
504   gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button),
505                             "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy),
506                             GTK_OBJECT(file_save_as_w));
507
508   /* Catch the "key_press_event" signal in the window, so that we can catch
509      the ESC key being pressed and act as if the "Cancel" button had
510      been selected. */
511   dlg_set_cancel(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
512
513   gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
514
515   gtk_widget_show(file_save_as_w);
516 }
517
518 /*
519  * Set the "Save only marked packets" toggle button as appropriate for
520  * the current output file type and count of marked packets.
521  *
522  * Called when the "Save As..." dialog box is created and when either
523  * the file type or the marked count changes.
524  */
525 void
526 file_set_save_marked_sensitive(void)
527 {
528   if (file_save_as_w == NULL) {
529     /* We don't currently have a "Save As..." dialog box up. */
530     return;
531   }
532
533   /* We can request that only the marked packets be saved only if we
534      can use Wiretap to save the file and if there *are* marked packets. */
535   if (can_save_with_wiretap(filetype) && cfile.marked_count != 0)
536     gtk_widget_set_sensitive(mark_cb, TRUE);
537   else {
538     /* Force the "Save only marked packets" toggle to "false", turn
539        off the flag it controls, and update the list of types we can
540        save the file as. */
541     marked = FALSE;
542     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(mark_cb), FALSE);
543     set_file_type_list(ft_om);
544     gtk_widget_set_sensitive(mark_cb, FALSE);
545   }
546 }
547
548 static void
549 file_save_as_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
550   gchar *cf_name;
551
552   cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
553   gtk_widget_hide(GTK_WIDGET (fs));
554   gtk_widget_destroy(GTK_WIDGET (fs));
555
556   /* Write out the packets (all, or only the ones that are currently
557      displayed or marked) to the file with the specified name. */
558   save_cap_file(cf_name, &cfile, filtered, marked, filetype);
559
560   /* If "save_cap_file()" saved the file name we handed it, it saved
561      a copy, so we should free up our copy. */
562   g_free(cf_name);
563 }
564
565 static void
566 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
567 {
568   /* Note that we no longer have a "Save Capture File As" dialog box. */
569   file_save_as_w = NULL;
570 }
571
572 /* Reload a file using the current read and display filters */
573 void
574 file_reload_cmd_cb(GtkWidget *w, gpointer data _U_) {
575   /*GtkWidget *filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);*/
576   GtkWidget *filter_te;
577   gchar *filename;
578   gboolean is_tempfile;
579   int err;
580
581   filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY);
582
583   if (cfile.dfilter)
584     g_free(cfile.dfilter);
585   cfile.dfilter = g_strdup(gtk_entry_get_text(GTK_ENTRY(filter_te)));
586
587   /* If the file could be opened, "open_cap_file()" calls "close_cap_file()"
588      to get rid of state for the old capture file before filling in state
589      for the new capture file.  "close_cap_file()" will remove the file if
590      it's a temporary file; we don't want that to happen (for one thing,
591      it'd prevent subsequent reopens from working).  Remember whether it's
592      a temporary file, mark it as not being a temporary file, and then
593      reopen it as the type of file it was.
594
595      Also, "close_cap_file()" will free "cfile.filename", so we must make
596      a copy of it first. */
597   filename = g_strdup(cfile.filename);
598   is_tempfile = cfile.is_tempfile;
599   cfile.is_tempfile = FALSE;
600   if (open_cap_file(filename, is_tempfile, &cfile) == 0) {
601     switch (read_cap_file(&cfile, &err)) {
602
603     case READ_SUCCESS:
604     case READ_ERROR:
605       /* Just because we got an error, that doesn't mean we were unable
606          to read any of the file; we handle what we could get from the
607          file. */
608       break;
609
610     case READ_ABORTED:
611       /* The user bailed out of re-reading the capture file; the
612          capture file has been closed - just free the capture file name
613          string and return (without changing the last containing
614          directory). */
615       g_free(filename);
616       return;
617     }
618   } else {
619     /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
620        Instead, the file was left open, so we should restore "cfile.is_tempfile"
621        ourselves.
622
623        XXX - change the menu?  Presumably "open_cap_file()" will do that;
624        make sure it does! */
625     cfile.is_tempfile = is_tempfile;
626   }
627   /* "open_cap_file()" made a copy of the file name we handed it, so
628      we should free up our copy. */
629   g_free(filename);
630 }