2 * Dialog boxes for handling files
4 * $Id: file_dlg.c,v 1.99 2004/03/27 11:16:58 oabad Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
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.
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.
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.
32 #include <epan/filesystem.h>
35 #include "gtkglobals.h"
36 #include <epan/resolv.h>
38 #include "filter_prefs.h"
40 #include "alert_box.h"
41 #include "simple_dialog.h"
44 #include "dlg_utils.h"
46 #include "compat_macros.h"
50 #include "../ui_util.h"
51 #include "gtk/color_filters.h"
52 #include "gtk/color_dlg.h"
54 #include "capture_dlg.h"
58 static void file_open_ok_cb(GtkWidget *w, gpointer fs);
59 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
60 static void select_file_type_cb(GtkWidget *w, gpointer data);
61 static void file_save_as_ok_cb(GtkWidget *w, gpointer fs);
62 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
63 static void file_color_import_ok_cb(GtkWidget *w, gpointer fs);
64 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
65 static void file_color_export_ok_cb(GtkWidget *w, gpointer fs);
66 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
67 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || GTK_MAJOR_VERSION < 2
68 static void file_select_ok_cb(GtkWidget *w, gpointer data);
69 static void file_select_cancel_cb(GtkWidget *w, gpointer data);
71 static void file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te);
72 static void toggle_captured_cb(GtkWidget *widget, gpointer data _U_);
74 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
75 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
76 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
78 #define ARGUMENT_CL "argument_cl"
81 * Keep a static pointer to the current "Save Capture File As" window, if
82 * any, so that if somebody tries to do "File:Save" or "File:Save As"
83 * while there's already a "Save Capture File As" window up, we just pop
84 * up the existing one, rather than creating a new one.
86 static GtkWidget *file_save_as_w;
89 * A generic select_file_cb routine that is intended to be connected to
90 * a Browse button on other dialog boxes. This allows the user to browse
91 * for a file and select it. We fill in the text_entry that is asssociated
92 * with the button that invoked us.
94 * We display the window label specified in our args.
97 select_file_cb(GtkWidget *file_bt, const char *label)
99 GtkWidget *caller = gtk_widget_get_toplevel(file_bt);
100 GtkWidget *fs, *file_te;
103 /* Has a file selection dialog box already been opened for that top-level
105 fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
106 file_te = OBJECT_GET_DATA(file_bt, E_FILE_TE_PTR_KEY);
108 /* Yes. Just re-activate that dialog box. */
109 reactivate_window(fs);
113 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
114 fs = file_selection_new(label, GTK_FILE_CHOOSER_ACTION_SAVE);
116 fs = file_selection_new(label);
119 /* If we've opened a file, start out by showing the files in the directory
120 in which that file resided. */
121 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
123 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs), last_open_dir);
126 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
129 OBJECT_SET_DATA(fs, PRINT_FILE_TE_KEY, file_te);
131 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
132 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
134 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
135 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
137 /* Call a handler when the file selection box is destroyed, so we can inform
138 our caller, if any, that it's been destroyed. */
139 SIGNAL_CONNECT(fs, "destroy", GTK_SIGNAL_FUNC(file_select_destroy_cb),
142 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
143 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
145 f_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
146 gtk_entry_set_text(GTK_ENTRY(file_te), f_name);
149 gtk_widget_destroy(fs);
151 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked",
152 file_select_ok_cb, fs);
154 /* Connect the cancel_button to destroy the widget */
155 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked",
156 file_select_cancel_cb, fs);
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
161 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
167 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || GTK_MAJOR_VERSION < 2
169 file_select_ok_cb(GtkWidget *w _U_, gpointer data)
173 f_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (data)));
175 /* Perhaps the user specified a directory instead of a file.
176 Check whether they did. */
177 if (test_for_directory(f_name) == EISDIR) {
178 /* It's a directory - set the file selection box to display it. */
179 set_last_open_dir(f_name);
181 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
186 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, PRINT_FILE_TE_KEY)),
188 gtk_widget_destroy(GTK_WIDGET(data));
194 file_select_cancel_cb(GtkWidget *w _U_, gpointer data)
196 gtk_widget_destroy(GTK_WIDGET(data));
201 file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te)
205 /* Get the widget that requested that we be popped up.
206 (It should arrange to destroy us if it's destroyed, so
207 that we don't get a pointer to a non-existent window here.) */
208 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
210 /* Tell it we no longer exist. */
211 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
213 /* Now nuke this window. */
214 gtk_grab_remove(GTK_WIDGET(win));
215 gtk_widget_destroy(GTK_WIDGET(win));
217 /* Give the focus to the file text entry widget so the user can just press
218 Return to print to the file. */
219 gtk_widget_grab_focus(file_te);
223 * Keep a static pointer to the current "Open Capture File" window, if
224 * any, so that if somebody tries to do "File:Open" while there's already
225 * an "Open Capture File" window up, we just pop up the existing one,
226 * rather than creating a new one.
228 static GtkWidget *file_open_w;
232 file_open_cmd(GtkWidget *w)
234 GtkWidget *main_vb, *filter_hbox, *filter_bt, *filter_te,
235 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
236 #if GTK_MAJOR_VERSION < 2
237 GtkAccelGroup *accel_group;
239 /* No Apply button, and "OK" just sets our text widget, it doesn't
240 activate it (i.e., it doesn't cause us to try to open the file). */
241 static construct_args_t args = {
242 "Ethereal: Read Filter",
247 if (file_open_w != NULL) {
248 /* There's already an "Open Capture File" dialog box; reactivate it. */
249 reactivate_window(file_open_w);
253 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
254 file_open_w = file_selection_new("Ethereal: Open Capture File",
255 GTK_FILE_CHOOSER_ACTION_OPEN);
257 file_open_w = file_selection_new("Ethereal: Open Capture File");
259 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
261 #if GTK_MAJOR_VERSION < 2
262 /* Accelerator group for the accelerators (or, as they're called in
263 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
264 Ctrl+<key> is an accelerator). */
265 accel_group = gtk_accel_group_new();
266 gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
269 switch (prefs.gui_fileopen_style) {
271 case FO_STYLE_LAST_OPENED:
272 /* The user has specified that we should start out in the last directory
273 we looked in. If we've already opened a file, use its containing
274 directory, if we could determine it, as the directory, otherwise
275 use the "last opened" directory saved in the preferences file if
277 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
279 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_open_w),
284 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
290 case FO_STYLE_SPECIFIED:
291 /* The user has specified that we should always start out in a
292 specified directory; if they've specified that directory,
293 start out by showing the files in that dir. */
294 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
295 if (prefs.gui_fileopen_dir[0] != '\0') {
296 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_open_w),
297 prefs.gui_fileopen_dir);
300 if (prefs.gui_fileopen_dir[0] != '\0') {
301 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
302 prefs.gui_fileopen_dir);
308 /* Container for each row of widgets */
309 main_vb = gtk_vbox_new(FALSE, 3);
310 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
311 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
312 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_open_w), main_vb);
314 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_open_w)->action_area),
315 main_vb, FALSE, FALSE, 0);
317 gtk_widget_show(main_vb);
319 filter_hbox = gtk_hbox_new(FALSE, 1);
320 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
321 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
322 gtk_widget_show(filter_hbox);
324 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
325 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
326 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
327 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
328 gtk_widget_show(filter_bt);
330 filter_te = gtk_entry_new();
331 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
332 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
333 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
334 gtk_widget_show(filter_te);
336 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
337 OBJECT_SET_DATA(file_open_w, E_RFILTER_TE_KEY, filter_te);
339 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
340 E_RFILTER_TE_KEY, filter_te);
343 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
344 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
345 g_resolv_flags & RESOLV_MAC);
346 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
347 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
348 OBJECT_SET_DATA(file_open_w,
349 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
351 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
352 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
354 gtk_widget_show(m_resolv_cb);
356 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
357 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
358 g_resolv_flags & RESOLV_NETWORK);
359 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
360 gtk_widget_show(n_resolv_cb);
361 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
362 OBJECT_SET_DATA(file_open_w, E_FILE_N_RESOLVE_KEY, n_resolv_cb);
364 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
365 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
368 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
369 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
370 g_resolv_flags & RESOLV_TRANSPORT);
371 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
372 gtk_widget_show(t_resolv_cb);
373 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
374 OBJECT_SET_DATA(file_open_w, E_FILE_T_RESOLVE_KEY, t_resolv_cb);
376 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
377 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
380 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
381 OBJECT_SET_DATA(file_open_w, E_DFILTER_TE_KEY,
382 OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
383 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
385 file_open_ok_cb(file_open_w, file_open_w);
387 else gtk_widget_destroy(file_open_w);
389 /* Connect the ok_button to file_open_ok_cb function and pass along a
390 pointer to the file selection box widget */
391 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
392 file_open_ok_cb, file_open_w);
394 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
395 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
397 /* Connect the cancel_button to destroy the widget */
398 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button,
399 "clicked", (GtkSignalFunc)gtk_widget_destroy,
402 /* Catch the "key_press_event" signal in the window, so that we can catch
403 the ESC key being pressed and act as if the "Cancel" button had
405 dlg_set_cancel(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
407 gtk_widget_show(file_open_w);
411 void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
415 /* save file first */
416 file_save_as_cmd(after_save_open_dialog, data);
422 case(ESD_BTN_CANCEL):
425 g_assert_not_reached();
430 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
433 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
434 /* user didn't saved his current file, ask him */
435 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
436 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
437 "If you open a new capture file without saving, your capture data will be discarded.");
438 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
440 /* unchanged file, just open a new one */
441 file_open_cmd(widget);
446 file_open_ok_cb(GtkWidget *w, gpointer fs) {
447 gchar *cf_name, *rfilter, *s;
448 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
449 dfilter_t *rfcode = NULL;
452 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
453 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
455 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
457 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
458 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
459 if (!dfilter_compile(rfilter, &rfcode)) {
460 bad_dfilter_alert_box(rfilter);
465 /* Perhaps the user specified a directory instead of a file.
466 Check whether they did. */
467 if (test_for_directory(cf_name) == EISDIR) {
468 /* It's a directory - set the file selection box to display that
469 directory, don't try to open the directory as a capture file. */
470 set_last_open_dir(cf_name);
472 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
476 /* Try to open the capture file. */
477 if ((err = cf_open(cf_name, FALSE, &cfile)) != 0) {
478 /* We couldn't open it; don't dismiss the open dialog box,
479 just leave it around so that the user can, after they
480 dismiss the alert box popped up for the open error,
483 dfilter_free(rfcode);
488 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
489 it closed the previous capture file, and thus destroyed any
490 previous read filter attached to "cf"). */
491 cfile.rfcode = rfcode;
493 /* Set the global resolving variable */
494 g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
495 m_resolv_cb = OBJECT_GET_DATA(w, E_FILE_M_RESOLVE_KEY);
496 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)) ? RESOLV_MAC : RESOLV_NONE;
497 n_resolv_cb = OBJECT_GET_DATA(w, E_FILE_N_RESOLVE_KEY);
498 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)) ? RESOLV_NETWORK : RESOLV_NONE;
499 t_resolv_cb = OBJECT_GET_DATA(w, E_FILE_T_RESOLVE_KEY);
500 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)) ? RESOLV_TRANSPORT : RESOLV_NONE;
502 /* We've crossed the Rubicon; get rid of the file selection box. */
503 gtk_widget_hide(GTK_WIDGET (fs));
504 gtk_widget_destroy(GTK_WIDGET (fs));
506 switch (cf_read(&cfile)) {
510 /* Just because we got an error, that doesn't mean we were unable
511 to read any of the file; we handle what we could get from the
516 /* The user bailed out of re-reading the capture file; the
517 capture file has been closed - just free the capture file name
518 string and return (without changing the last containing
524 /* Save the name of the containing directory specified in the path name,
525 if any; we can write over cf_name, which is a good thing, given that
526 "get_dirname()" does write over its argument. */
527 s = get_dirname(cf_name);
528 set_last_open_dir(s);
529 gtk_widget_grab_focus(packet_list);
535 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
537 /* Note that we no longer have a "Open Capture File" dialog box. */
541 void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
545 /* save file first */
546 file_save_as_cmd(after_save_close_file, NULL);
551 case(ESD_BTN_CANCEL):
554 g_assert_not_reached();
560 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
563 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
564 /* user didn't saved his current file, ask him */
565 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
566 PRIMARY_TEXT_START "Save capture file before closing it?" PRIMARY_TEXT_END "\n\n"
567 "If you close without saving, your capture data will be discarded.");
569 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
571 /* unchanged file, just close it */
577 file_save_cmd_cb(GtkWidget *w, gpointer data) {
578 /* If the file's already been saved, do nothing. */
579 if (cfile.user_saved)
582 /* Do a "Save As". */
583 file_save_as_cmd_cb(w, data);
586 /* XXX - can we make these not be static? */
587 static packet_range_t range;
588 static gboolean color_marked;
590 static GtkWidget *captured_bt;
591 static GtkWidget *displayed_bt;
592 static GtkWidget *select_all_rb;
593 static GtkWidget *select_all_c_lb;
594 static GtkWidget *select_all_d_lb;
595 static GtkWidget *select_curr_rb;
596 static GtkWidget *select_curr_c_lb;
597 static GtkWidget *select_curr_d_lb;
598 static GtkWidget *select_marked_only_rb;
599 static GtkWidget *select_marked_only_c_lb;
600 static GtkWidget *select_marked_only_d_lb;
601 static GtkWidget *select_marked_range_rb;
602 static GtkWidget *select_marked_range_c_lb;
603 static GtkWidget *select_marked_range_d_lb;
604 static GtkWidget *select_user_range_rb;
605 static GtkWidget *select_user_range_c_lb;
606 static GtkWidget *select_user_range_d_lb;
607 static GtkWidget *select_user_range_entry;
608 static GtkWidget *cfmark_cb;
609 static GtkWidget *ft_om;
612 can_save_with_wiretap(int ft)
614 /* To save a file with Wiretap, Wiretap has to handle that format,
615 and its code to handle that format must be able to write a file
616 with this file's encapsulation type. */
617 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
621 file_set_save_dynamics(void) {
622 gboolean filtered_active;
623 gchar label_text[100];
627 filtered_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displayed_bt));
629 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(filetype));
631 gtk_widget_set_sensitive(select_all_c_lb, !filtered_active);
632 g_snprintf(label_text, sizeof(label_text), "%u", cfile.count);
633 gtk_label_set_text(GTK_LABEL(select_all_c_lb), label_text);
634 gtk_widget_set_sensitive(select_all_d_lb, filtered_active);
635 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_cnt);
637 gtk_label_set_text(GTK_LABEL(select_all_d_lb), label_text);
639 selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
640 /* XXX: how to update the radio button label but keep the mnemonic? */
641 /* g_snprintf(label_text, sizeof(label_text), "_Selected packet #%u only", selected_num);
642 gtk_label_set_text(GTK_LABEL(GTK_BIN(select_curr_rb)->child), label_text);*/
643 gtk_widget_set_sensitive(select_curr_rb, selected_num);
644 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
645 gtk_label_set_text(GTK_LABEL(select_curr_c_lb), label_text);
646 gtk_widget_set_sensitive(select_curr_c_lb, selected_num && !filtered_active);
647 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
648 gtk_label_set_text(GTK_LABEL(select_curr_d_lb), label_text);
649 gtk_widget_set_sensitive(select_curr_d_lb, selected_num && filtered_active);
651 gtk_widget_set_sensitive(select_marked_only_rb, cfile.marked_count);
652 g_snprintf(label_text, sizeof(label_text), "%u", cfile.marked_count);
653 gtk_label_set_text(GTK_LABEL(select_marked_only_c_lb), label_text);
654 gtk_widget_set_sensitive(select_marked_only_c_lb, cfile.marked_count && !filtered_active);
655 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_marked_cnt);
656 gtk_label_set_text(GTK_LABEL(select_marked_only_d_lb), label_text);
657 gtk_widget_set_sensitive(select_marked_only_d_lb, range.displayed_marked_cnt && filtered_active);
659 gtk_widget_set_sensitive(select_marked_range_rb, range.mark_range_cnt);
660 g_snprintf(label_text, sizeof(label_text), "%u", range.mark_range_cnt);
661 gtk_label_set_text(GTK_LABEL(select_marked_range_c_lb), label_text);
662 gtk_widget_set_sensitive(select_marked_range_c_lb, range.mark_range_cnt && !filtered_active);
663 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_mark_range_cnt);
664 gtk_label_set_text(GTK_LABEL(select_marked_range_d_lb), label_text);
665 gtk_widget_set_sensitive(select_marked_range_d_lb, range.displayed_mark_range_cnt && filtered_active);
667 gtk_widget_set_sensitive(select_user_range_rb, TRUE);
668 g_snprintf(label_text, sizeof(label_text), "%u", range.user_range_cnt);
669 gtk_label_set_text(GTK_LABEL(select_user_range_c_lb), label_text);
670 gtk_widget_set_sensitive(select_user_range_c_lb, !filtered_active);
671 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_user_range_cnt);
672 gtk_label_set_text(GTK_LABEL(select_user_range_d_lb), label_text);
673 gtk_widget_set_sensitive(select_user_range_d_lb, filtered_active);
676 /* Generate a list of the file types we can save this file as.
678 "filetype" is the type it has now.
680 "encap" is the encapsulation for its packets (which could be
681 "unknown" or "per-packet").
683 "filtered" is TRUE if we're to save only the packets that passed
684 the display filter (in which case we have to save it using Wiretap)
685 and FALSE if we're to save the entire file (in which case, if we're
686 saving it in the type it has already, we can just copy it).
688 The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
691 set_file_type_list(GtkWidget *option_menu)
693 GtkWidget *ft_menu, *ft_menu_item;
696 guint item_to_select;
698 /* Default to the first supported file type, if the file's current
699 type isn't supported. */
702 ft_menu = gtk_menu_new();
704 /* Check all file types. */
706 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
707 if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
708 /* not all unfiltered packets or a different file type. We have to use Wiretap. */
709 if (!can_save_with_wiretap(ft))
710 continue; /* We can't. */
713 /* OK, we can write it out in this type. */
714 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
715 if (ft == filetype) {
716 /* Default to the same format as the file, if it's supported. */
717 item_to_select = index;
719 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
720 GINT_TO_POINTER(ft));
721 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
722 gtk_widget_show(ft_menu_item);
726 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
727 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
731 select_file_type_cb(GtkWidget *w _U_, gpointer data)
733 int new_filetype = GPOINTER_TO_INT(data);
735 if (filetype != new_filetype) {
736 /* We can select only the filtered or marked packets to be saved if we can
737 use Wiretap to save the file. */
738 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(new_filetype));
739 filetype = new_filetype;
740 file_set_save_marked_sensitive();
745 toggle_captured_cb(GtkWidget *widget, gpointer data _U_)
747 /* is the button now active? */
748 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
749 /* They changed the state of the "captured" button. */
750 range.process_filtered = FALSE;
751 /* XXX: the following line fails, I have no idea why */
752 /* set_file_type_list(ft_om);*/
754 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
755 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
757 file_set_save_dynamics();
762 toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
764 /* is the button now active? */
765 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
766 range.process_filtered = TRUE;
767 set_file_type_list(ft_om);
769 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), FALSE);
770 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), TRUE);
772 file_set_save_dynamics();
777 toggle_select_all(GtkWidget *widget, gpointer data _U_)
779 /* is the button now active? */
780 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
781 range.process = range_process_all;
782 set_file_type_list(ft_om);
783 file_set_save_dynamics();
788 toggle_select_selected(GtkWidget *widget, gpointer data _U_)
790 /* is the button now active? */
791 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
792 range.process = range_process_selected;
793 set_file_type_list(ft_om);
794 file_set_save_dynamics();
799 toggle_select_marked_only(GtkWidget *widget, gpointer data _U_)
801 /* is the button now active? */
802 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
803 range.process = range_process_marked;
804 set_file_type_list(ft_om);
805 file_set_save_dynamics();
810 toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
812 /* is the button now active? */
813 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
814 range.process = range_process_marked_range;
815 set_file_type_list(ft_om);
816 file_set_save_dynamics();
821 toggle_select_user_range(GtkWidget *widget, gpointer data _U_)
823 /* is the button now active? */
824 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
825 range.process = range_process_user_range;
826 set_file_type_list(ft_om);
827 file_set_save_dynamics();
830 /* Make the entry widget sensitive or insensitive */
831 gtk_widget_set_sensitive(select_user_range_entry, range.process == range_process_user_range);
833 /* When selecting user specified range, then focus on the entry */
834 if (range.process == range_process_user_range)
835 gtk_widget_grab_focus(select_user_range_entry);
840 range_entry(GtkWidget *entry)
842 const gchar *entry_text;
844 entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
845 packet_range_convert_str(&range, entry_text);
846 file_set_save_dynamics();
850 * Set the "Save only marked packets" toggle button as appropriate for
851 * the current output file type and count of marked packets.
853 * Called when the "Save As..." dialog box is created and when either
854 * the file type or the marked count changes.
857 file_set_save_marked_sensitive(void)
859 if (file_save_as_w == NULL) {
860 /* We don't currently have a "Save As..." dialog box up. */
864 /* We can request that only the marked packets be saved only if we
865 can use Wiretap to save the file and if there *are* marked packets. */
866 if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
867 gtk_widget_set_sensitive(select_marked_only_rb, TRUE);
868 gtk_widget_set_sensitive(select_marked_range_rb, TRUE);
871 /* Force the "Save only marked packets" toggle to "false", turn
872 off the flag it controls, and update the list of types we can
874 range.process = range_process_all;
875 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_only_rb), FALSE);
876 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_range_rb), FALSE);
877 set_file_type_list(ft_om);
878 gtk_widget_set_sensitive(select_marked_only_rb, FALSE);
879 gtk_widget_set_sensitive(select_marked_range_rb, FALSE);
883 action_after_save_e action_after_save_g;
884 gpointer action_after_save_data_g;
888 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
890 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *range_tb;
891 GtkTooltips *tooltips;
893 #if GTK_MAJOR_VERSION < 2
894 GtkAccelGroup *accel_group;
897 if (file_save_as_w != NULL) {
898 /* There's already an "Save Capture File As" dialog box; reactivate it. */
899 reactivate_window(file_save_as_w);
903 /* Default to saving all packets, in the file's current format. */
904 filetype = cfile.cd_t;
906 /* init the packet range */
907 packet_range_init(&range);
909 /* Enable tooltips */
910 tooltips = gtk_tooltips_new();
912 /* build the file selection */
913 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
914 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As",
915 GTK_FILE_CHOOSER_ACTION_SAVE);
917 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As");
919 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
921 /* as the dialog might already be gone, when using this values, we cannot
922 * set data to the dialog object, but keep global values */
923 action_after_save_g = action_after_save;
924 action_after_save_data_g = action_after_save_data;
926 #if GTK_MAJOR_VERSION < 2
927 accel_group = gtk_accel_group_new();
928 gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
931 /* If we've opened a file, start out by showing the files in the directory
932 in which that file resided. */
933 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
935 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_save_as_w),
939 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w),
943 /* Container for each row of widgets */
945 main_vb = gtk_vbox_new(FALSE, 5);
946 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
947 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
948 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_save_as_w), main_vb);
950 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
951 main_vb, FALSE, FALSE, 0);
953 gtk_widget_show(main_vb);
955 /*** Packet Range frame ***/
956 range_fr = gtk_frame_new("Packet Range");
957 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
958 gtk_widget_show(range_fr);
961 range_tb = gtk_table_new(7, 3, FALSE);
962 gtk_container_border_width(GTK_CONTAINER(range_tb), 5);
963 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
964 gtk_widget_show(range_tb);
966 /* captured button */
967 captured_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Captured", accel_group);
968 gtk_table_attach_defaults(GTK_TABLE(range_tb), captured_bt, 1, 2, 0, 1);
969 SIGNAL_CONNECT(captured_bt, "toggled", toggle_captured_cb, NULL);
970 gtk_tooltips_set_tip (tooltips,captured_bt,("Process all the below chosen packets"), NULL);
971 gtk_widget_show(captured_bt);
973 /* displayed button */
974 displayed_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Displayed", accel_group);
975 gtk_table_attach_defaults(GTK_TABLE(range_tb), displayed_bt, 2, 3, 0, 1);
976 SIGNAL_CONNECT(displayed_bt, "toggled", toggle_filtered_cb, NULL);
977 gtk_tooltips_set_tip (tooltips,displayed_bt,("Process only the below chosen packets, which also passes the current display filter"), NULL);
978 gtk_widget_show(displayed_bt);
981 /* Process all packets */
982 select_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "_All packets", accel_group);
983 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 1, 2);
984 gtk_tooltips_set_tip (tooltips,select_all_rb,("Process all packets"), NULL);
985 SIGNAL_CONNECT(select_all_rb, "toggled", toggle_select_all, NULL);
986 gtk_widget_show(select_all_rb);
988 select_all_c_lb = gtk_label_new("?");
989 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_c_lb, 1, 2, 1, 2);
990 gtk_widget_show(select_all_c_lb);
991 select_all_d_lb = gtk_label_new("?");
992 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_d_lb, 2, 3, 1, 2);
993 gtk_widget_show(select_all_d_lb);
996 /* Process currently selected */
997 select_curr_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Selected packet only", accel_group);
998 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_rb, 0, 1, 2, 3);
999 gtk_tooltips_set_tip (tooltips,select_curr_rb,("Process the currently selected packet only"), NULL);
1000 SIGNAL_CONNECT(select_curr_rb, "toggled", toggle_select_selected, NULL);
1001 gtk_widget_show(select_curr_rb);
1003 select_curr_c_lb = gtk_label_new("?");
1004 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_c_lb, 1, 2, 2, 3);
1005 gtk_widget_show(select_curr_c_lb);
1006 select_curr_d_lb = gtk_label_new("?");
1007 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_d_lb, 2, 3, 2, 3);
1008 gtk_widget_show(select_curr_d_lb);
1011 /* Process marked packets */
1012 select_marked_only_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Marked packets only", accel_group);
1013 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_rb, 0, 1, 3, 4);
1014 gtk_tooltips_set_tip (tooltips,select_marked_only_rb,("Process marked packets only"), NULL);
1015 SIGNAL_CONNECT(select_marked_only_rb, "toggled", toggle_select_marked_only, NULL);
1016 gtk_widget_show(select_marked_only_rb);
1018 select_marked_only_c_lb = gtk_label_new("?");
1019 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_c_lb, 1, 2, 3, 4);
1020 gtk_widget_show(select_marked_only_c_lb);
1021 select_marked_only_d_lb = gtk_label_new("?");
1022 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_d_lb, 2, 3, 3, 4);
1023 gtk_widget_show(select_marked_only_d_lb);
1026 /* Process packet range between first and last packet */
1027 select_marked_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "From first _to last marked packet", accel_group);
1028 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_rb, 0, 1, 4, 5);
1029 gtk_tooltips_set_tip (tooltips,select_marked_range_rb,("Process all packets between the first and last marker"), NULL);
1030 SIGNAL_CONNECT(select_marked_range_rb, "toggled", toggle_select_marked_range, NULL);
1031 gtk_widget_show(select_marked_range_rb);
1033 select_marked_range_c_lb = gtk_label_new("?");
1034 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_c_lb, 1, 2, 4, 5);
1035 gtk_widget_show(select_marked_range_c_lb);
1036 select_marked_range_d_lb = gtk_label_new("?");
1037 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_d_lb, 2, 3, 4, 5);
1038 gtk_widget_show(select_marked_range_d_lb);
1041 /* Process a user specified provided packet range : -10,30,40-70,80- */
1042 select_user_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "Specify a packet _range:", accel_group);
1043 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_rb, 0, 1, 5, 6);
1044 gtk_tooltips_set_tip (tooltips,select_user_range_rb,("Process a specified packet range"), NULL);
1045 SIGNAL_CONNECT(select_user_range_rb, "toggled", toggle_select_user_range, NULL);
1046 gtk_widget_show(select_user_range_rb);
1048 select_user_range_c_lb = gtk_label_new("?");
1049 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_c_lb, 1, 2, 5, 6);
1050 gtk_widget_show(select_user_range_c_lb);
1051 select_user_range_d_lb = gtk_label_new("?");
1052 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_d_lb, 2, 3, 5, 6);
1053 gtk_widget_show(select_user_range_d_lb);
1056 /* The entry part */
1057 select_user_range_entry = gtk_entry_new();
1058 gtk_entry_set_max_length (GTK_ENTRY (select_user_range_entry), 254);
1059 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_entry, 0, 1, 6, 7);
1060 gtk_tooltips_set_tip (tooltips,select_user_range_entry,
1061 ("Specify a range of packet numbers : \nExample : 1-10,18,25-100,332-"), NULL);
1062 SIGNAL_CONNECT(select_user_range_entry,"changed", range_entry, select_user_range_entry);
1063 gtk_widget_set_sensitive(select_user_range_entry, FALSE);
1064 gtk_widget_show(select_user_range_entry);
1066 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
1067 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
1068 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb), TRUE);
1071 ft_hb = gtk_hbox_new(FALSE, 3);
1072 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1073 gtk_widget_show(ft_hb);
1075 ft_lb = gtk_label_new("File type:");
1076 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1077 gtk_widget_show(ft_lb);
1079 ft_om = gtk_option_menu_new();
1081 /* Generate the list of file types we can save. */
1082 set_file_type_list(ft_om);
1083 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1084 gtk_widget_show(ft_om);
1087 * Set the sensitivity of the "Save only marked packets" toggle
1090 * This has to be done after we create the file type menu option,
1091 * as the routine that sets it also sets that menu.
1093 file_set_save_marked_sensitive();
1095 /* dynamic values in the range frame */
1096 file_set_save_dynamics();
1098 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1099 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT)
1101 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1103 else gtk_widget_destroy(file_save_as_w);
1105 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
1106 pointer to the file selection box widget */
1107 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_save_as_w)->ok_button, "clicked",
1108 file_save_as_ok_cb, file_save_as_w);
1110 /* Connect the cancel_button to destroy the widget */
1111 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
1112 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1115 /* Catch the "key_press_event" signal in the window, so that we can catch
1116 the ESC key being pressed and act as if the "Cancel" button had
1118 dlg_set_cancel(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
1120 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
1122 gtk_widget_show(file_save_as_w);
1127 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1129 file_save_as_cmd(after_save_no_action, NULL);
1133 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1137 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1138 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1140 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1143 /* Perhaps the user specified a directory instead of a file.
1144 Check whether they did. */
1145 if (test_for_directory(cf_name) == EISDIR) {
1146 /* It's a directory - set the file selection box to display that
1147 directory, and leave the selection box displayed. */
1148 set_last_open_dir(cf_name);
1150 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1154 /* don't show the dialog while saving */
1155 gtk_widget_hide(GTK_WIDGET (fs));
1157 /* Write out the packets (all, or only the ones from the current
1158 range) to the file with the specified name. */
1159 if (! cf_save(cf_name, &cfile, &range, filetype)) {
1160 /* The write failed; don't dismiss the open dialog box,
1161 just leave it around so that the user can, after they
1162 dismiss the alert box popped up for the error, try again. */
1164 gtk_widget_show(GTK_WIDGET (fs));
1168 /* The write succeeded; get rid of the file selection box. */
1169 /* cf_save might already closed our dialog! */
1171 gtk_widget_destroy(GTK_WIDGET (fs));
1173 /* Save the directory name for future file dialogs. */
1174 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1175 set_last_open_dir(dirname);
1178 /* we have finished saving, do we have pending things to do? */
1179 switch(action_after_save_g) {
1180 case(after_save_no_action):
1182 case(after_save_open_dialog):
1183 file_open_cmd(action_after_save_data_g);
1185 case(after_save_open_recent_file):
1186 menu_open_recent_file_cmd(action_after_save_data_g);
1188 case(after_save_open_dnd_file):
1189 dnd_open_file_cmd(action_after_save_data_g);
1192 case(after_save_capture_dialog):
1196 case(after_save_close_file):
1199 case(after_save_exit):
1203 g_assert_not_reached();
1206 action_after_save_g = after_save_no_action;
1210 file_save_as_destroy(void)
1213 gtk_widget_destroy(file_save_as_w);
1217 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1219 /* Note that we no longer have a "Save Capture File As" dialog box. */
1220 file_save_as_w = NULL;
1223 /* Reload a file using the current read and display filters */
1225 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1227 gboolean is_tempfile;
1229 /* If the file could be opened, "cf_open()" calls "cf_close()"
1230 to get rid of state for the old capture file before filling in state
1231 for the new capture file. "cf_close()" will remove the file if
1232 it's a temporary file; we don't want that to happen (for one thing,
1233 it'd prevent subsequent reopens from working). Remember whether it's
1234 a temporary file, mark it as not being a temporary file, and then
1235 reopen it as the type of file it was.
1237 Also, "cf_close()" will free "cfile.filename", so we must make
1238 a copy of it first. */
1239 filename = g_strdup(cfile.filename);
1240 is_tempfile = cfile.is_tempfile;
1241 cfile.is_tempfile = FALSE;
1242 if (cf_open(filename, is_tempfile, &cfile) == 0) {
1243 switch (cf_read(&cfile)) {
1247 /* Just because we got an error, that doesn't mean we were unable
1248 to read any of the file; we handle what we could get from the
1253 /* The user bailed out of re-reading the capture file; the
1254 capture file has been closed - just free the capture file name
1255 string and return (without changing the last containing
1261 /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
1262 Instead, the file was left open, so we should restore "cfile.is_tempfile"
1265 XXX - change the menu? Presumably "cf_open()" will do that;
1266 make sure it does! */
1267 cfile.is_tempfile = is_tempfile;
1269 /* "cf_open()" made a copy of the file name we handed it, so
1270 we should free up our copy. */
1274 /******************** Color Filters *********************************/
1276 * Keep a static pointer to the current "Color Export" window, if
1277 * any, so that if somebody tries to do "Export"
1278 * while there's already a "Color Export" window up, we just pop
1279 * up the existing one, rather than creating a new one.
1281 static GtkWidget *file_color_import_w;
1283 /* sets the file path to the global color filter file.
1284 WARNING: called by both the import and the export dialog.
1287 color_global_cb(GtkWidget *widget _U_, gpointer data)
1289 GtkWidget *fs_widget = data;
1292 /* decide what file to open (from dfilter code) */
1293 path = get_datafile_path("colorfilters");
1295 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1296 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1298 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs_widget), path);
1300 g_free((gchar *)path);
1303 /* Import color filters */
1305 file_color_import_cmd_cb(GtkWidget *w _U_, gpointer data)
1307 GtkWidget *main_vb, *cfglobal_but;
1308 #if GTK_MAJOR_VERSION < 2
1309 GtkAccelGroup *accel_group;
1311 /* No Apply button, and "OK" just sets our text widget, it doesn't
1312 activate it (i.e., it doesn't cause us to try to open the file). */
1314 if (file_color_import_w != NULL) {
1315 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1316 reactivate_window(file_color_import_w);
1320 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1321 file_color_import_w = file_selection_new("Ethereal: Import Color Filters",
1322 GTK_FILE_CHOOSER_ACTION_OPEN);
1324 file_color_import_w = gtk_file_selection_new("Ethereal: Import Color Filters");
1326 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1328 #if GTK_MAJOR_VERSION < 2
1329 /* Accelerator group for the accelerators (or, as they're called in
1330 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
1331 Ctrl+<key> is an accelerator). */
1332 accel_group = gtk_accel_group_new();
1333 gtk_window_add_accel_group(GTK_WINDOW(file_color_import_w), accel_group);
1336 /* If we've opened a file, start out by showing the files in the directory
1337 in which that file resided. */
1338 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1340 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_color_import_w),
1344 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_import_w),
1348 /* Container for each row of widgets */
1349 main_vb = gtk_vbox_new(FALSE, 3);
1350 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1351 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1352 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_color_import_w),
1355 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_import_w)->action_area),
1356 main_vb, FALSE, FALSE, 0);
1358 gtk_widget_show(main_vb);
1361 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1362 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1363 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1364 gtk_widget_show(cfglobal_but);
1366 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1367 OBJECT_SET_DATA(file_color_import_w, ARGUMENT_CL, data);
1369 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1371 file_color_import_ok_cb(file_color_import_w, file_color_import_w);
1373 else gtk_widget_destroy(file_color_import_w);
1375 /* Connect the ok_button to file_open_ok_cb function and pass along a
1376 pointer to the file selection box widget */
1377 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1378 file_color_import_ok_cb, file_color_import_w);
1380 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_color_import_w)->ok_button,
1383 /* Connect the cancel_button to destroy the widget */
1384 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_import_w)->cancel_button,
1385 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1386 file_color_import_w);
1388 /* Catch the "key_press_event" signal in the window, so that we can catch
1389 the ESC key being pressed and act as if the "Cancel" button had
1391 dlg_set_cancel(file_color_import_w, GTK_FILE_SELECTION(file_color_import_w)->cancel_button);
1393 gtk_widget_show(file_color_import_w);
1398 file_color_import_ok_cb(GtkWidget *w, gpointer fs) {
1402 argument = OBJECT_GET_DATA(w, ARGUMENT_CL); /* to be passed back into read_other_filters */
1404 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1405 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1407 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1409 /* Perhaps the user specified a directory instead of a file.
1410 Check whether they did. */
1411 if (test_for_directory(cf_name) == EISDIR) {
1412 /* It's a directory - set the file selection box to display that
1413 directory, don't try to open the directory as a capture file. */
1414 set_last_open_dir(cf_name);
1416 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1420 /* Try to open the capture file. */
1422 if (!read_other_filters(cf_name, argument)) {
1423 /* We couldn't open it; don't dismiss the open dialog box,
1424 just leave it around so that the user can, after they
1425 dismiss the alert box popped up for the open error,
1431 /* We've crossed the Rubicon; get rid of the file selection box. */
1432 gtk_widget_hide(GTK_WIDGET (fs));
1433 gtk_widget_destroy(GTK_WIDGET (fs));
1435 /* Save the name of the containing directory specified in the path name,
1436 if any; we can write over cf_name, which is a good thing, given that
1437 "get_dirname()" does write over its argument. */
1438 s = get_dirname(cf_name);
1439 set_last_open_dir(s);
1440 gtk_widget_grab_focus(packet_list);
1446 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1448 /* Note that we no longer have a "Open Capture File" dialog box. */
1449 file_color_import_w = NULL;
1452 static GtkWidget *file_color_export_w;
1454 * Set the "Export only marked filters" toggle button as appropriate for
1455 * the current output file type and count of marked filters.
1457 * Called when the "Export" dialog box is created and when the marked
1461 color_set_export_marked_sensitive(GtkWidget * cfmark_cb)
1463 if (file_color_export_w == NULL) {
1464 /* We don't currently have an "Export" dialog box up. */
1468 /* We can request that only the marked filters be saved only if
1469 there *are* marked filters. */
1470 if (color_marked_count() != 0)
1471 gtk_widget_set_sensitive(cfmark_cb, TRUE);
1473 /* Force the "Export only marked filters" toggle to "false", turn
1474 off the flag it controls. */
1475 color_marked = FALSE;
1476 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1477 gtk_widget_set_sensitive(cfmark_cb, FALSE);
1482 color_toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
1484 color_marked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1488 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1490 GtkWidget *main_vb, *cfglobal_but;
1492 if (file_color_export_w != NULL) {
1493 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1494 reactivate_window(file_color_export_w);
1498 /* Default to saving all packets, in the file's current format. */
1499 color_marked = FALSE;
1500 filetype = cfile.cd_t;
1502 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1503 file_color_export_w = file_selection_new("Ethereal: Export Color Filters",
1504 GTK_FILE_CHOOSER_ACTION_SAVE);
1506 file_color_export_w = gtk_file_selection_new("Ethereal: Export Color Filters");
1508 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1510 /* If we've opened a file, start out by showing the files in the directory
1511 in which that file resided. */
1512 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1514 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_color_export_w),
1518 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w),
1522 /* Container for each row of widgets */
1523 main_vb = gtk_vbox_new(FALSE, 3);
1524 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1525 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1526 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_color_export_w),
1529 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_export_w)->action_area),
1530 main_vb, FALSE, FALSE, 0);
1532 gtk_widget_show(main_vb);
1534 cfmark_cb = gtk_check_button_new_with_label("Export only marked filters");
1535 gtk_container_add(GTK_CONTAINER(main_vb), cfmark_cb);
1536 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1537 SIGNAL_CONNECT(cfmark_cb, "toggled", color_toggle_marked_cb, NULL);
1538 gtk_widget_show(cfmark_cb);
1539 color_set_export_marked_sensitive(cfmark_cb);
1541 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1542 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1543 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1544 gtk_widget_show(cfglobal_but);
1546 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1547 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1549 file_color_export_ok_cb(file_color_export_w, file_color_export_w);
1551 else gtk_widget_destroy(file_color_export_w);
1553 /* Connect the ok_button to file_export_ok_cb function and pass along a
1554 pointer to the file selection box widget */
1555 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_color_export_w)->ok_button, "clicked",
1556 file_color_export_ok_cb, file_color_export_w);
1558 /* Connect the cancel_button to destroy the widget */
1559 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_export_w)->cancel_button,
1560 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1561 file_color_export_w);
1563 /* Catch the "key_press_event" signal in the window, so that we can catch
1564 the ESC key being pressed and act as if the "Cancel" button had
1566 dlg_set_cancel(file_color_export_w, GTK_FILE_SELECTION(file_color_export_w)->cancel_button);
1568 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1570 gtk_widget_show(file_color_export_w);
1575 file_color_export_ok_cb(GtkWidget *w _U_, gpointer fs) {
1579 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1580 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1582 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1585 /* Perhaps the user specified a directory instead of a file.
1586 Check whether they did. */
1587 if (test_for_directory(cf_name) == EISDIR) {
1588 /* It's a directory - set the file selection box to display that
1589 directory, and leave the selection box displayed. */
1590 set_last_open_dir(cf_name);
1592 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1596 /* Write out the filters (all, or only the ones that are currently
1597 displayed or marked) to the file with the specified name. */
1599 if (!write_other_filters(cf_name, color_marked))
1601 /* The write failed; don't dismiss the open dialog box,
1602 just leave it around so that the user can, after they
1603 dismiss the alert box popped up for the error, try again. */
1609 /* The write succeeded; get rid of the file selection box. */
1610 gtk_widget_hide(GTK_WIDGET (fs));
1611 gtk_widget_destroy(GTK_WIDGET (fs));
1613 /* Save the directory name for future file dialogs. */
1614 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1615 set_last_open_dir(dirname);
1620 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1622 file_color_export_w = NULL;