2 * Dialog boxes for handling files
4 * $Id: file_dlg.c,v 1.100 2004/03/27 12:18:40 ulfl 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;
101 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
105 /* Has a file selection dialog box already been opened for that top-level
107 fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
108 file_te = OBJECT_GET_DATA(file_bt, E_FILE_TE_PTR_KEY);
110 /* Yes. Just re-activate that dialog box. */
111 reactivate_window(fs);
115 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
116 fs = file_selection_new(label, GTK_FILE_CHOOSER_ACTION_SAVE);
118 fs = file_selection_new(label);
121 /* If we've opened a file, start out by showing the files in the directory
122 in which that file resided. */
124 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
125 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(fs), last_open_dir);
127 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
130 OBJECT_SET_DATA(fs, PRINT_FILE_TE_KEY, file_te);
132 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
133 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
135 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
136 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
138 /* Call a handler when the file selection box is destroyed, so we can inform
139 our caller, if any, that it's been destroyed. */
140 SIGNAL_CONNECT(fs, "destroy", GTK_SIGNAL_FUNC(file_select_destroy_cb),
143 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
144 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
146 f_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
147 gtk_entry_set_text(GTK_ENTRY(file_te), f_name);
150 gtk_widget_destroy(fs);
152 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked",
153 file_select_ok_cb, fs);
155 /* Connect the cancel_button to destroy the widget */
156 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked",
157 file_select_cancel_cb, fs);
159 /* Catch the "key_press_event" signal in the window, so that we can catch
160 the ESC key being pressed and act as if the "Cancel" button had
162 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
168 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || GTK_MAJOR_VERSION < 2
170 file_select_ok_cb(GtkWidget *w _U_, gpointer data)
174 f_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (data)));
176 /* Perhaps the user specified a directory instead of a file.
177 Check whether they did. */
178 if (test_for_directory(f_name) == EISDIR) {
179 /* It's a directory - set the file selection box to display it. */
180 set_last_open_dir(f_name);
182 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
187 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, PRINT_FILE_TE_KEY)),
189 gtk_widget_destroy(GTK_WIDGET(data));
195 file_select_cancel_cb(GtkWidget *w _U_, gpointer data)
197 gtk_widget_destroy(GTK_WIDGET(data));
202 file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te)
206 /* Get the widget that requested that we be popped up.
207 (It should arrange to destroy us if it's destroyed, so
208 that we don't get a pointer to a non-existent window here.) */
209 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
211 /* Tell it we no longer exist. */
212 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
214 /* Now nuke this window. */
215 gtk_grab_remove(GTK_WIDGET(win));
216 gtk_widget_destroy(GTK_WIDGET(win));
218 /* Give the focus to the file text entry widget so the user can just press
219 Return to print to the file. */
220 gtk_widget_grab_focus(file_te);
224 * Keep a static pointer to the current "Open Capture File" window, if
225 * any, so that if somebody tries to do "File:Open" while there's already
226 * an "Open Capture File" window up, we just pop up the existing one,
227 * rather than creating a new one.
229 static GtkWidget *file_open_w;
233 file_open_cmd(GtkWidget *w)
235 GtkWidget *main_vb, *filter_hbox, *filter_bt, *filter_te,
236 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
237 #if GTK_MAJOR_VERSION < 2
238 GtkAccelGroup *accel_group;
240 /* No Apply button, and "OK" just sets our text widget, it doesn't
241 activate it (i.e., it doesn't cause us to try to open the file). */
242 static construct_args_t args = {
243 "Ethereal: Read Filter",
248 if (file_open_w != NULL) {
249 /* There's already an "Open Capture File" dialog box; reactivate it. */
250 reactivate_window(file_open_w);
254 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
255 file_open_w = file_selection_new("Ethereal: Open Capture File",
256 GTK_FILE_CHOOSER_ACTION_OPEN);
258 file_open_w = file_selection_new("Ethereal: Open Capture File");
260 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
262 #if GTK_MAJOR_VERSION < 2
263 /* Accelerator group for the accelerators (or, as they're called in
264 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
265 Ctrl+<key> is an accelerator). */
266 accel_group = gtk_accel_group_new();
267 gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
270 switch (prefs.gui_fileopen_style) {
272 case FO_STYLE_LAST_OPENED:
273 /* The user has specified that we should start out in the last directory
274 we looked in. If we've already opened a file, use its containing
275 directory, if we could determine it, as the directory, otherwise
276 use the "last opened" directory saved in the preferences file if
279 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
280 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_open_w),
283 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
289 case FO_STYLE_SPECIFIED:
290 /* The user has specified that we should always start out in a
291 specified directory; if they've specified that directory,
292 start out by showing the files in that dir. */
293 if (prefs.gui_fileopen_dir[0] != '\0') {
294 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
295 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_open_w),
296 prefs.gui_fileopen_dir);
298 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
299 prefs.gui_fileopen_dir);
305 /* Container for each row of widgets */
306 main_vb = gtk_vbox_new(FALSE, 3);
307 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
308 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
309 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_open_w), main_vb);
311 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_open_w)->action_area),
312 main_vb, FALSE, FALSE, 0);
314 gtk_widget_show(main_vb);
316 filter_hbox = gtk_hbox_new(FALSE, 1);
317 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
318 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
319 gtk_widget_show(filter_hbox);
321 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
322 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
323 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
324 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
325 gtk_widget_show(filter_bt);
327 filter_te = gtk_entry_new();
328 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
329 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
330 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
331 gtk_widget_show(filter_te);
333 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
334 OBJECT_SET_DATA(file_open_w, E_RFILTER_TE_KEY, filter_te);
336 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
337 E_RFILTER_TE_KEY, filter_te);
340 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
341 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
342 g_resolv_flags & RESOLV_MAC);
343 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
344 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
345 OBJECT_SET_DATA(file_open_w,
346 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
348 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
349 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
351 gtk_widget_show(m_resolv_cb);
353 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
354 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
355 g_resolv_flags & RESOLV_NETWORK);
356 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
357 gtk_widget_show(n_resolv_cb);
358 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
359 OBJECT_SET_DATA(file_open_w, E_FILE_N_RESOLVE_KEY, n_resolv_cb);
361 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
362 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
365 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
366 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
367 g_resolv_flags & RESOLV_TRANSPORT);
368 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
369 gtk_widget_show(t_resolv_cb);
370 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
371 OBJECT_SET_DATA(file_open_w, E_FILE_T_RESOLVE_KEY, t_resolv_cb);
373 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
374 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
377 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
378 OBJECT_SET_DATA(file_open_w, E_DFILTER_TE_KEY,
379 OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
380 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
382 file_open_ok_cb(file_open_w, file_open_w);
384 else gtk_widget_destroy(file_open_w);
386 /* Connect the ok_button to file_open_ok_cb function and pass along a
387 pointer to the file selection box widget */
388 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
389 file_open_ok_cb, file_open_w);
391 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
392 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
394 /* Connect the cancel_button to destroy the widget */
395 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button,
396 "clicked", (GtkSignalFunc)gtk_widget_destroy,
399 /* Catch the "key_press_event" signal in the window, so that we can catch
400 the ESC key being pressed and act as if the "Cancel" button had
402 dlg_set_cancel(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
404 gtk_widget_show(file_open_w);
408 void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
412 /* save file first */
413 file_save_as_cmd(after_save_open_dialog, data);
419 case(ESD_BTN_CANCEL):
422 g_assert_not_reached();
427 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
430 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
431 /* user didn't saved his current file, ask him */
432 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
433 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
434 "If you open a new capture file without saving, your capture data will be discarded.");
435 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
437 /* unchanged file, just open a new one */
438 file_open_cmd(widget);
443 file_open_ok_cb(GtkWidget *w, gpointer fs) {
444 gchar *cf_name, *rfilter, *s;
445 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
446 dfilter_t *rfcode = NULL;
449 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
450 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
452 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
454 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
455 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
456 if (!dfilter_compile(rfilter, &rfcode)) {
457 bad_dfilter_alert_box(rfilter);
462 /* Perhaps the user specified a directory instead of a file.
463 Check whether they did. */
464 if (test_for_directory(cf_name) == EISDIR) {
465 /* It's a directory - set the file selection box to display that
466 directory, don't try to open the directory as a capture file. */
467 set_last_open_dir(cf_name);
469 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
473 /* Try to open the capture file. */
474 if ((err = cf_open(cf_name, FALSE, &cfile)) != 0) {
475 /* We couldn't open it; don't dismiss the open dialog box,
476 just leave it around so that the user can, after they
477 dismiss the alert box popped up for the open error,
480 dfilter_free(rfcode);
485 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
486 it closed the previous capture file, and thus destroyed any
487 previous read filter attached to "cf"). */
488 cfile.rfcode = rfcode;
490 /* Set the global resolving variable */
491 g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
492 m_resolv_cb = OBJECT_GET_DATA(w, E_FILE_M_RESOLVE_KEY);
493 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)) ? RESOLV_MAC : RESOLV_NONE;
494 n_resolv_cb = OBJECT_GET_DATA(w, E_FILE_N_RESOLVE_KEY);
495 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)) ? RESOLV_NETWORK : RESOLV_NONE;
496 t_resolv_cb = OBJECT_GET_DATA(w, E_FILE_T_RESOLVE_KEY);
497 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)) ? RESOLV_TRANSPORT : RESOLV_NONE;
499 /* We've crossed the Rubicon; get rid of the file selection box. */
500 gtk_widget_hide(GTK_WIDGET (fs));
501 gtk_widget_destroy(GTK_WIDGET (fs));
503 switch (cf_read(&cfile)) {
507 /* Just because we got an error, that doesn't mean we were unable
508 to read any of the file; we handle what we could get from the
513 /* The user bailed out of re-reading the capture file; the
514 capture file has been closed - just free the capture file name
515 string and return (without changing the last containing
521 /* Save the name of the containing directory specified in the path name,
522 if any; we can write over cf_name, which is a good thing, given that
523 "get_dirname()" does write over its argument. */
524 s = get_dirname(cf_name);
525 set_last_open_dir(s);
526 gtk_widget_grab_focus(packet_list);
532 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
534 /* Note that we no longer have a "Open Capture File" dialog box. */
538 void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
542 /* save file first */
543 file_save_as_cmd(after_save_close_file, NULL);
548 case(ESD_BTN_CANCEL):
551 g_assert_not_reached();
557 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
560 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
561 /* user didn't saved his current file, ask him */
562 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
563 PRIMARY_TEXT_START "Save capture file before closing it?" PRIMARY_TEXT_END "\n\n"
564 "If you close without saving, your capture data will be discarded.");
566 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
568 /* unchanged file, just close it */
574 file_save_cmd_cb(GtkWidget *w, gpointer data) {
575 /* If the file's already been saved, do nothing. */
576 if (cfile.user_saved)
579 /* Do a "Save As". */
580 file_save_as_cmd_cb(w, data);
583 /* XXX - can we make these not be static? */
584 static packet_range_t range;
585 static gboolean color_marked;
587 static GtkWidget *captured_bt;
588 static GtkWidget *displayed_bt;
589 static GtkWidget *select_all_rb;
590 static GtkWidget *select_all_c_lb;
591 static GtkWidget *select_all_d_lb;
592 static GtkWidget *select_curr_rb;
593 static GtkWidget *select_curr_c_lb;
594 static GtkWidget *select_curr_d_lb;
595 static GtkWidget *select_marked_only_rb;
596 static GtkWidget *select_marked_only_c_lb;
597 static GtkWidget *select_marked_only_d_lb;
598 static GtkWidget *select_marked_range_rb;
599 static GtkWidget *select_marked_range_c_lb;
600 static GtkWidget *select_marked_range_d_lb;
601 static GtkWidget *select_user_range_rb;
602 static GtkWidget *select_user_range_c_lb;
603 static GtkWidget *select_user_range_d_lb;
604 static GtkWidget *select_user_range_entry;
605 static GtkWidget *cfmark_cb;
606 static GtkWidget *ft_om;
609 can_save_with_wiretap(int ft)
611 /* To save a file with Wiretap, Wiretap has to handle that format,
612 and its code to handle that format must be able to write a file
613 with this file's encapsulation type. */
614 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
618 file_set_save_dynamics(void) {
619 gboolean filtered_active;
620 gchar label_text[100];
624 filtered_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displayed_bt));
626 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(filetype));
628 gtk_widget_set_sensitive(select_all_c_lb, !filtered_active);
629 g_snprintf(label_text, sizeof(label_text), "%u", cfile.count);
630 gtk_label_set_text(GTK_LABEL(select_all_c_lb), label_text);
631 gtk_widget_set_sensitive(select_all_d_lb, filtered_active);
632 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_cnt);
634 gtk_label_set_text(GTK_LABEL(select_all_d_lb), label_text);
636 selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
637 /* XXX: how to update the radio button label but keep the mnemonic? */
638 /* g_snprintf(label_text, sizeof(label_text), "_Selected packet #%u only", selected_num);
639 gtk_label_set_text(GTK_LABEL(GTK_BIN(select_curr_rb)->child), label_text);*/
640 gtk_widget_set_sensitive(select_curr_rb, selected_num);
641 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
642 gtk_label_set_text(GTK_LABEL(select_curr_c_lb), label_text);
643 gtk_widget_set_sensitive(select_curr_c_lb, selected_num && !filtered_active);
644 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
645 gtk_label_set_text(GTK_LABEL(select_curr_d_lb), label_text);
646 gtk_widget_set_sensitive(select_curr_d_lb, selected_num && filtered_active);
648 gtk_widget_set_sensitive(select_marked_only_rb, cfile.marked_count);
649 g_snprintf(label_text, sizeof(label_text), "%u", cfile.marked_count);
650 gtk_label_set_text(GTK_LABEL(select_marked_only_c_lb), label_text);
651 gtk_widget_set_sensitive(select_marked_only_c_lb, cfile.marked_count && !filtered_active);
652 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_marked_cnt);
653 gtk_label_set_text(GTK_LABEL(select_marked_only_d_lb), label_text);
654 gtk_widget_set_sensitive(select_marked_only_d_lb, range.displayed_marked_cnt && filtered_active);
656 gtk_widget_set_sensitive(select_marked_range_rb, range.mark_range_cnt);
657 g_snprintf(label_text, sizeof(label_text), "%u", range.mark_range_cnt);
658 gtk_label_set_text(GTK_LABEL(select_marked_range_c_lb), label_text);
659 gtk_widget_set_sensitive(select_marked_range_c_lb, range.mark_range_cnt && !filtered_active);
660 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_mark_range_cnt);
661 gtk_label_set_text(GTK_LABEL(select_marked_range_d_lb), label_text);
662 gtk_widget_set_sensitive(select_marked_range_d_lb, range.displayed_mark_range_cnt && filtered_active);
664 gtk_widget_set_sensitive(select_user_range_rb, TRUE);
665 g_snprintf(label_text, sizeof(label_text), "%u", range.user_range_cnt);
666 gtk_label_set_text(GTK_LABEL(select_user_range_c_lb), label_text);
667 gtk_widget_set_sensitive(select_user_range_c_lb, !filtered_active);
668 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_user_range_cnt);
669 gtk_label_set_text(GTK_LABEL(select_user_range_d_lb), label_text);
670 gtk_widget_set_sensitive(select_user_range_d_lb, filtered_active);
673 /* Generate a list of the file types we can save this file as.
675 "filetype" is the type it has now.
677 "encap" is the encapsulation for its packets (which could be
678 "unknown" or "per-packet").
680 "filtered" is TRUE if we're to save only the packets that passed
681 the display filter (in which case we have to save it using Wiretap)
682 and FALSE if we're to save the entire file (in which case, if we're
683 saving it in the type it has already, we can just copy it).
685 The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
688 set_file_type_list(GtkWidget *option_menu)
690 GtkWidget *ft_menu, *ft_menu_item;
693 guint item_to_select;
695 /* Default to the first supported file type, if the file's current
696 type isn't supported. */
699 ft_menu = gtk_menu_new();
701 /* Check all file types. */
703 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
704 if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
705 /* not all unfiltered packets or a different file type. We have to use Wiretap. */
706 if (!can_save_with_wiretap(ft))
707 continue; /* We can't. */
710 /* OK, we can write it out in this type. */
711 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
712 if (ft == filetype) {
713 /* Default to the same format as the file, if it's supported. */
714 item_to_select = index;
716 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
717 GINT_TO_POINTER(ft));
718 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
719 gtk_widget_show(ft_menu_item);
723 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
724 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
728 select_file_type_cb(GtkWidget *w _U_, gpointer data)
730 int new_filetype = GPOINTER_TO_INT(data);
732 if (filetype != new_filetype) {
733 /* We can select only the filtered or marked packets to be saved if we can
734 use Wiretap to save the file. */
735 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(new_filetype));
736 filetype = new_filetype;
737 file_set_save_marked_sensitive();
742 toggle_captured_cb(GtkWidget *widget, gpointer data _U_)
744 /* is the button now active? */
745 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
746 /* They changed the state of the "captured" button. */
747 range.process_filtered = FALSE;
748 /* XXX: the following line fails, I have no idea why */
749 /* set_file_type_list(ft_om);*/
751 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
752 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
754 file_set_save_dynamics();
759 toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
761 /* is the button now active? */
762 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
763 range.process_filtered = TRUE;
764 set_file_type_list(ft_om);
766 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), FALSE);
767 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), TRUE);
769 file_set_save_dynamics();
774 toggle_select_all(GtkWidget *widget, gpointer data _U_)
776 /* is the button now active? */
777 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
778 range.process = range_process_all;
779 set_file_type_list(ft_om);
780 file_set_save_dynamics();
785 toggle_select_selected(GtkWidget *widget, gpointer data _U_)
787 /* is the button now active? */
788 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
789 range.process = range_process_selected;
790 set_file_type_list(ft_om);
791 file_set_save_dynamics();
796 toggle_select_marked_only(GtkWidget *widget, gpointer data _U_)
798 /* is the button now active? */
799 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
800 range.process = range_process_marked;
801 set_file_type_list(ft_om);
802 file_set_save_dynamics();
807 toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
809 /* is the button now active? */
810 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
811 range.process = range_process_marked_range;
812 set_file_type_list(ft_om);
813 file_set_save_dynamics();
818 toggle_select_user_range(GtkWidget *widget, gpointer data _U_)
820 /* is the button now active? */
821 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
822 range.process = range_process_user_range;
823 set_file_type_list(ft_om);
824 file_set_save_dynamics();
827 /* Make the entry widget sensitive or insensitive */
828 gtk_widget_set_sensitive(select_user_range_entry, range.process == range_process_user_range);
830 /* When selecting user specified range, then focus on the entry */
831 if (range.process == range_process_user_range)
832 gtk_widget_grab_focus(select_user_range_entry);
837 range_entry(GtkWidget *entry)
839 const gchar *entry_text;
841 entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
842 packet_range_convert_str(&range, entry_text);
843 file_set_save_dynamics();
847 * Set the "Save only marked packets" toggle button as appropriate for
848 * the current output file type and count of marked packets.
850 * Called when the "Save As..." dialog box is created and when either
851 * the file type or the marked count changes.
854 file_set_save_marked_sensitive(void)
856 if (file_save_as_w == NULL) {
857 /* We don't currently have a "Save As..." dialog box up. */
861 /* We can request that only the marked packets be saved only if we
862 can use Wiretap to save the file and if there *are* marked packets. */
863 if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
864 gtk_widget_set_sensitive(select_marked_only_rb, TRUE);
865 gtk_widget_set_sensitive(select_marked_range_rb, TRUE);
868 /* Force the "Save only marked packets" toggle to "false", turn
869 off the flag it controls, and update the list of types we can
871 range.process = range_process_all;
872 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_only_rb), FALSE);
873 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_range_rb), FALSE);
874 set_file_type_list(ft_om);
875 gtk_widget_set_sensitive(select_marked_only_rb, FALSE);
876 gtk_widget_set_sensitive(select_marked_range_rb, FALSE);
880 action_after_save_e action_after_save_g;
881 gpointer action_after_save_data_g;
885 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
887 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *range_tb;
888 GtkTooltips *tooltips;
890 #if GTK_MAJOR_VERSION < 2
891 GtkAccelGroup *accel_group;
894 if (file_save_as_w != NULL) {
895 /* There's already an "Save Capture File As" dialog box; reactivate it. */
896 reactivate_window(file_save_as_w);
900 /* Default to saving all packets, in the file's current format. */
901 filetype = cfile.cd_t;
903 /* init the packet range */
904 packet_range_init(&range);
906 /* Enable tooltips */
907 tooltips = gtk_tooltips_new();
909 /* build the file selection */
910 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
911 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As",
912 GTK_FILE_CHOOSER_ACTION_SAVE);
914 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As");
916 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
918 /* as the dialog might already be gone, when using this values, we cannot
919 * set data to the dialog object, but keep global values */
920 action_after_save_g = action_after_save;
921 action_after_save_data_g = action_after_save_data;
923 #if GTK_MAJOR_VERSION < 2
924 accel_group = gtk_accel_group_new();
925 gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
928 /* If we've opened a file, start out by showing the files in the directory
929 in which that file resided. */
931 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
932 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_save_as_w),
935 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w),
939 /* Container for each row of widgets */
941 main_vb = gtk_vbox_new(FALSE, 5);
942 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
943 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
944 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_save_as_w), main_vb);
946 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
947 main_vb, FALSE, FALSE, 0);
949 gtk_widget_show(main_vb);
951 /*** Packet Range frame ***/
952 range_fr = gtk_frame_new("Packet Range");
953 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
954 gtk_widget_show(range_fr);
957 range_tb = gtk_table_new(7, 3, FALSE);
958 gtk_container_border_width(GTK_CONTAINER(range_tb), 5);
959 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
960 gtk_widget_show(range_tb);
962 /* captured button */
963 captured_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Captured", accel_group);
964 gtk_table_attach_defaults(GTK_TABLE(range_tb), captured_bt, 1, 2, 0, 1);
965 SIGNAL_CONNECT(captured_bt, "toggled", toggle_captured_cb, NULL);
966 gtk_tooltips_set_tip (tooltips,captured_bt,("Process all the below chosen packets"), NULL);
967 gtk_widget_show(captured_bt);
969 /* displayed button */
970 displayed_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Displayed", accel_group);
971 gtk_table_attach_defaults(GTK_TABLE(range_tb), displayed_bt, 2, 3, 0, 1);
972 SIGNAL_CONNECT(displayed_bt, "toggled", toggle_filtered_cb, NULL);
973 gtk_tooltips_set_tip (tooltips,displayed_bt,("Process only the below chosen packets, which also passes the current display filter"), NULL);
974 gtk_widget_show(displayed_bt);
977 /* Process all packets */
978 select_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "_All packets", accel_group);
979 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 1, 2);
980 gtk_tooltips_set_tip (tooltips,select_all_rb,("Process all packets"), NULL);
981 SIGNAL_CONNECT(select_all_rb, "toggled", toggle_select_all, NULL);
982 gtk_widget_show(select_all_rb);
984 select_all_c_lb = gtk_label_new("?");
985 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_c_lb, 1, 2, 1, 2);
986 gtk_widget_show(select_all_c_lb);
987 select_all_d_lb = gtk_label_new("?");
988 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_d_lb, 2, 3, 1, 2);
989 gtk_widget_show(select_all_d_lb);
992 /* Process currently selected */
993 select_curr_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Selected packet only", accel_group);
994 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_rb, 0, 1, 2, 3);
995 gtk_tooltips_set_tip (tooltips,select_curr_rb,("Process the currently selected packet only"), NULL);
996 SIGNAL_CONNECT(select_curr_rb, "toggled", toggle_select_selected, NULL);
997 gtk_widget_show(select_curr_rb);
999 select_curr_c_lb = gtk_label_new("?");
1000 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_c_lb, 1, 2, 2, 3);
1001 gtk_widget_show(select_curr_c_lb);
1002 select_curr_d_lb = gtk_label_new("?");
1003 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_d_lb, 2, 3, 2, 3);
1004 gtk_widget_show(select_curr_d_lb);
1007 /* Process marked packets */
1008 select_marked_only_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Marked packets only", accel_group);
1009 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_rb, 0, 1, 3, 4);
1010 gtk_tooltips_set_tip (tooltips,select_marked_only_rb,("Process marked packets only"), NULL);
1011 SIGNAL_CONNECT(select_marked_only_rb, "toggled", toggle_select_marked_only, NULL);
1012 gtk_widget_show(select_marked_only_rb);
1014 select_marked_only_c_lb = gtk_label_new("?");
1015 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_c_lb, 1, 2, 3, 4);
1016 gtk_widget_show(select_marked_only_c_lb);
1017 select_marked_only_d_lb = gtk_label_new("?");
1018 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_d_lb, 2, 3, 3, 4);
1019 gtk_widget_show(select_marked_only_d_lb);
1022 /* Process packet range between first and last packet */
1023 select_marked_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "From first _to last marked packet", accel_group);
1024 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_rb, 0, 1, 4, 5);
1025 gtk_tooltips_set_tip (tooltips,select_marked_range_rb,("Process all packets between the first and last marker"), NULL);
1026 SIGNAL_CONNECT(select_marked_range_rb, "toggled", toggle_select_marked_range, NULL);
1027 gtk_widget_show(select_marked_range_rb);
1029 select_marked_range_c_lb = gtk_label_new("?");
1030 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_c_lb, 1, 2, 4, 5);
1031 gtk_widget_show(select_marked_range_c_lb);
1032 select_marked_range_d_lb = gtk_label_new("?");
1033 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_d_lb, 2, 3, 4, 5);
1034 gtk_widget_show(select_marked_range_d_lb);
1037 /* Process a user specified provided packet range : -10,30,40-70,80- */
1038 select_user_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "Specify a packet _range:", accel_group);
1039 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_rb, 0, 1, 5, 6);
1040 gtk_tooltips_set_tip (tooltips,select_user_range_rb,("Process a specified packet range"), NULL);
1041 SIGNAL_CONNECT(select_user_range_rb, "toggled", toggle_select_user_range, NULL);
1042 gtk_widget_show(select_user_range_rb);
1044 select_user_range_c_lb = gtk_label_new("?");
1045 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_c_lb, 1, 2, 5, 6);
1046 gtk_widget_show(select_user_range_c_lb);
1047 select_user_range_d_lb = gtk_label_new("?");
1048 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_d_lb, 2, 3, 5, 6);
1049 gtk_widget_show(select_user_range_d_lb);
1052 /* The entry part */
1053 select_user_range_entry = gtk_entry_new();
1054 gtk_entry_set_max_length (GTK_ENTRY (select_user_range_entry), 254);
1055 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_entry, 0, 1, 6, 7);
1056 gtk_tooltips_set_tip (tooltips,select_user_range_entry,
1057 ("Specify a range of packet numbers : \nExample : 1-10,18,25-100,332-"), NULL);
1058 SIGNAL_CONNECT(select_user_range_entry,"changed", range_entry, select_user_range_entry);
1059 gtk_widget_set_sensitive(select_user_range_entry, FALSE);
1060 gtk_widget_show(select_user_range_entry);
1062 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
1063 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
1064 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb), TRUE);
1067 ft_hb = gtk_hbox_new(FALSE, 3);
1068 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1069 gtk_widget_show(ft_hb);
1071 ft_lb = gtk_label_new("File type:");
1072 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1073 gtk_widget_show(ft_lb);
1075 ft_om = gtk_option_menu_new();
1077 /* Generate the list of file types we can save. */
1078 set_file_type_list(ft_om);
1079 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1080 gtk_widget_show(ft_om);
1083 * Set the sensitivity of the "Save only marked packets" toggle
1086 * This has to be done after we create the file type menu option,
1087 * as the routine that sets it also sets that menu.
1089 file_set_save_marked_sensitive();
1091 /* dynamic values in the range frame */
1092 file_set_save_dynamics();
1094 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1095 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT)
1097 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1099 else gtk_widget_destroy(file_save_as_w);
1101 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
1102 pointer to the file selection box widget */
1103 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_save_as_w)->ok_button, "clicked",
1104 file_save_as_ok_cb, file_save_as_w);
1106 /* Connect the cancel_button to destroy the widget */
1107 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
1108 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1111 /* Catch the "key_press_event" signal in the window, so that we can catch
1112 the ESC key being pressed and act as if the "Cancel" button had
1114 dlg_set_cancel(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
1116 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
1118 gtk_widget_show(file_save_as_w);
1123 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1125 file_save_as_cmd(after_save_no_action, NULL);
1129 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1133 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1134 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1136 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1139 /* Perhaps the user specified a directory instead of a file.
1140 Check whether they did. */
1141 if (test_for_directory(cf_name) == EISDIR) {
1142 /* It's a directory - set the file selection box to display that
1143 directory, and leave the selection box displayed. */
1144 set_last_open_dir(cf_name);
1146 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1150 /* don't show the dialog while saving */
1151 gtk_widget_hide(GTK_WIDGET (fs));
1153 /* Write out the packets (all, or only the ones from the current
1154 range) to the file with the specified name. */
1155 if (! cf_save(cf_name, &cfile, &range, filetype)) {
1156 /* The write failed; don't dismiss the open dialog box,
1157 just leave it around so that the user can, after they
1158 dismiss the alert box popped up for the error, try again. */
1160 gtk_widget_show(GTK_WIDGET (fs));
1164 /* The write succeeded; get rid of the file selection box. */
1165 /* cf_save might already closed our dialog! */
1167 gtk_widget_destroy(GTK_WIDGET (fs));
1169 /* Save the directory name for future file dialogs. */
1170 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1171 set_last_open_dir(dirname);
1174 /* we have finished saving, do we have pending things to do? */
1175 switch(action_after_save_g) {
1176 case(after_save_no_action):
1178 case(after_save_open_dialog):
1179 file_open_cmd(action_after_save_data_g);
1181 case(after_save_open_recent_file):
1182 menu_open_recent_file_cmd(action_after_save_data_g);
1184 case(after_save_open_dnd_file):
1185 dnd_open_file_cmd(action_after_save_data_g);
1188 case(after_save_capture_dialog):
1192 case(after_save_close_file):
1195 case(after_save_exit):
1199 g_assert_not_reached();
1202 action_after_save_g = after_save_no_action;
1206 file_save_as_destroy(void)
1209 gtk_widget_destroy(file_save_as_w);
1213 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1215 /* Note that we no longer have a "Save Capture File As" dialog box. */
1216 file_save_as_w = NULL;
1219 /* Reload a file using the current read and display filters */
1221 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1223 gboolean is_tempfile;
1225 /* If the file could be opened, "cf_open()" calls "cf_close()"
1226 to get rid of state for the old capture file before filling in state
1227 for the new capture file. "cf_close()" will remove the file if
1228 it's a temporary file; we don't want that to happen (for one thing,
1229 it'd prevent subsequent reopens from working). Remember whether it's
1230 a temporary file, mark it as not being a temporary file, and then
1231 reopen it as the type of file it was.
1233 Also, "cf_close()" will free "cfile.filename", so we must make
1234 a copy of it first. */
1235 filename = g_strdup(cfile.filename);
1236 is_tempfile = cfile.is_tempfile;
1237 cfile.is_tempfile = FALSE;
1238 if (cf_open(filename, is_tempfile, &cfile) == 0) {
1239 switch (cf_read(&cfile)) {
1243 /* Just because we got an error, that doesn't mean we were unable
1244 to read any of the file; we handle what we could get from the
1249 /* The user bailed out of re-reading the capture file; the
1250 capture file has been closed - just free the capture file name
1251 string and return (without changing the last containing
1257 /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
1258 Instead, the file was left open, so we should restore "cfile.is_tempfile"
1261 XXX - change the menu? Presumably "cf_open()" will do that;
1262 make sure it does! */
1263 cfile.is_tempfile = is_tempfile;
1265 /* "cf_open()" made a copy of the file name we handed it, so
1266 we should free up our copy. */
1270 /******************** Color Filters *********************************/
1272 * Keep a static pointer to the current "Color Export" window, if
1273 * any, so that if somebody tries to do "Export"
1274 * while there's already a "Color Export" window up, we just pop
1275 * up the existing one, rather than creating a new one.
1277 static GtkWidget *file_color_import_w;
1279 /* sets the file path to the global color filter file.
1280 WARNING: called by both the import and the export dialog.
1283 color_global_cb(GtkWidget *widget _U_, gpointer data)
1285 GtkWidget *fs_widget = data;
1288 /* decide what file to open (from dfilter code) */
1289 path = get_datafile_path("colorfilters");
1291 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1292 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1294 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs_widget), path);
1296 g_free((gchar *)path);
1299 /* Import color filters */
1301 file_color_import_cmd_cb(GtkWidget *w _U_, gpointer data)
1303 GtkWidget *main_vb, *cfglobal_but;
1304 #if GTK_MAJOR_VERSION < 2
1305 GtkAccelGroup *accel_group;
1307 /* No Apply button, and "OK" just sets our text widget, it doesn't
1308 activate it (i.e., it doesn't cause us to try to open the file). */
1310 if (file_color_import_w != NULL) {
1311 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1312 reactivate_window(file_color_import_w);
1316 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1317 file_color_import_w = file_selection_new("Ethereal: Import Color Filters",
1318 GTK_FILE_CHOOSER_ACTION_OPEN);
1320 file_color_import_w = gtk_file_selection_new("Ethereal: Import Color Filters");
1322 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1324 #if GTK_MAJOR_VERSION < 2
1325 /* Accelerator group for the accelerators (or, as they're called in
1326 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
1327 Ctrl+<key> is an accelerator). */
1328 accel_group = gtk_accel_group_new();
1329 gtk_window_add_accel_group(GTK_WINDOW(file_color_import_w), accel_group);
1332 /* If we've opened a file, start out by showing the files in the directory
1333 in which that file resided. */
1335 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1336 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_color_import_w),
1339 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_import_w),
1343 /* Container for each row of widgets */
1344 main_vb = gtk_vbox_new(FALSE, 3);
1345 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1346 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1347 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_color_import_w),
1350 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_import_w)->action_area),
1351 main_vb, FALSE, FALSE, 0);
1353 gtk_widget_show(main_vb);
1356 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1357 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1358 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1359 gtk_widget_show(cfglobal_but);
1361 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1362 OBJECT_SET_DATA(file_color_import_w, ARGUMENT_CL, data);
1364 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1366 file_color_import_ok_cb(file_color_import_w, file_color_import_w);
1368 else gtk_widget_destroy(file_color_import_w);
1370 /* Connect the ok_button to file_open_ok_cb function and pass along a
1371 pointer to the file selection box widget */
1372 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1373 file_color_import_ok_cb, file_color_import_w);
1375 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_color_import_w)->ok_button,
1378 /* Connect the cancel_button to destroy the widget */
1379 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_import_w)->cancel_button,
1380 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1381 file_color_import_w);
1383 /* Catch the "key_press_event" signal in the window, so that we can catch
1384 the ESC key being pressed and act as if the "Cancel" button had
1386 dlg_set_cancel(file_color_import_w, GTK_FILE_SELECTION(file_color_import_w)->cancel_button);
1388 gtk_widget_show(file_color_import_w);
1393 file_color_import_ok_cb(GtkWidget *w, gpointer fs) {
1397 argument = OBJECT_GET_DATA(w, ARGUMENT_CL); /* to be passed back into read_other_filters */
1399 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1400 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1402 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1404 /* Perhaps the user specified a directory instead of a file.
1405 Check whether they did. */
1406 if (test_for_directory(cf_name) == EISDIR) {
1407 /* It's a directory - set the file selection box to display that
1408 directory, don't try to open the directory as a capture file. */
1409 set_last_open_dir(cf_name);
1411 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1415 /* Try to open the capture file. */
1417 if (!read_other_filters(cf_name, argument)) {
1418 /* We couldn't open it; don't dismiss the open dialog box,
1419 just leave it around so that the user can, after they
1420 dismiss the alert box popped up for the open error,
1426 /* We've crossed the Rubicon; get rid of the file selection box. */
1427 gtk_widget_hide(GTK_WIDGET (fs));
1428 gtk_widget_destroy(GTK_WIDGET (fs));
1430 /* Save the name of the containing directory specified in the path name,
1431 if any; we can write over cf_name, which is a good thing, given that
1432 "get_dirname()" does write over its argument. */
1433 s = get_dirname(cf_name);
1434 set_last_open_dir(s);
1435 gtk_widget_grab_focus(packet_list);
1441 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1443 /* Note that we no longer have a "Open Capture File" dialog box. */
1444 file_color_import_w = NULL;
1447 static GtkWidget *file_color_export_w;
1449 * Set the "Export only marked filters" toggle button as appropriate for
1450 * the current output file type and count of marked filters.
1452 * Called when the "Export" dialog box is created and when the marked
1456 color_set_export_marked_sensitive(GtkWidget * cfmark_cb)
1458 if (file_color_export_w == NULL) {
1459 /* We don't currently have an "Export" dialog box up. */
1463 /* We can request that only the marked filters be saved only if
1464 there *are* marked filters. */
1465 if (color_marked_count() != 0)
1466 gtk_widget_set_sensitive(cfmark_cb, TRUE);
1468 /* Force the "Export only marked filters" toggle to "false", turn
1469 off the flag it controls. */
1470 color_marked = FALSE;
1471 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1472 gtk_widget_set_sensitive(cfmark_cb, FALSE);
1477 color_toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
1479 color_marked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1483 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1485 GtkWidget *main_vb, *cfglobal_but;
1487 if (file_color_export_w != NULL) {
1488 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1489 reactivate_window(file_color_export_w);
1493 /* Default to saving all packets, in the file's current format. */
1494 color_marked = FALSE;
1495 filetype = cfile.cd_t;
1497 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1498 file_color_export_w = file_selection_new("Ethereal: Export Color Filters",
1499 GTK_FILE_CHOOSER_ACTION_SAVE);
1501 file_color_export_w = gtk_file_selection_new("Ethereal: Export Color Filters");
1503 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1505 /* If we've opened a file, start out by showing the files in the directory
1506 in which that file resided. */
1508 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1509 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_color_export_w),
1512 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w),
1516 /* Container for each row of widgets */
1517 main_vb = gtk_vbox_new(FALSE, 3);
1518 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1519 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1520 gtk_file_chooser_set_extra_widget(GTK_FILE_CHOOSER(file_color_export_w),
1523 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_export_w)->action_area),
1524 main_vb, FALSE, FALSE, 0);
1526 gtk_widget_show(main_vb);
1528 cfmark_cb = gtk_check_button_new_with_label("Export only marked filters");
1529 gtk_container_add(GTK_CONTAINER(main_vb), cfmark_cb);
1530 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1531 SIGNAL_CONNECT(cfmark_cb, "toggled", color_toggle_marked_cb, NULL);
1532 gtk_widget_show(cfmark_cb);
1533 color_set_export_marked_sensitive(cfmark_cb);
1535 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1536 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1537 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1538 gtk_widget_show(cfglobal_but);
1540 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1541 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1543 file_color_export_ok_cb(file_color_export_w, file_color_export_w);
1545 else gtk_widget_destroy(file_color_export_w);
1547 /* Connect the ok_button to file_export_ok_cb function and pass along a
1548 pointer to the file selection box widget */
1549 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_color_export_w)->ok_button, "clicked",
1550 file_color_export_ok_cb, file_color_export_w);
1552 /* Connect the cancel_button to destroy the widget */
1553 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_export_w)->cancel_button,
1554 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1555 file_color_export_w);
1557 /* Catch the "key_press_event" signal in the window, so that we can catch
1558 the ESC key being pressed and act as if the "Cancel" button had
1560 dlg_set_cancel(file_color_export_w, GTK_FILE_SELECTION(file_color_export_w)->cancel_button);
1562 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1564 gtk_widget_show(file_color_export_w);
1569 file_color_export_ok_cb(GtkWidget *w _U_, gpointer fs) {
1573 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1574 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1576 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1579 /* Perhaps the user specified a directory instead of a file.
1580 Check whether they did. */
1581 if (test_for_directory(cf_name) == EISDIR) {
1582 /* It's a directory - set the file selection box to display that
1583 directory, and leave the selection box displayed. */
1584 set_last_open_dir(cf_name);
1586 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1590 /* Write out the filters (all, or only the ones that are currently
1591 displayed or marked) to the file with the specified name. */
1593 if (!write_other_filters(cf_name, color_marked))
1595 /* The write failed; don't dismiss the open dialog box,
1596 just leave it around so that the user can, after they
1597 dismiss the alert box popped up for the error, try again. */
1603 /* The write succeeded; get rid of the file selection box. */
1604 gtk_widget_hide(GTK_WIDGET (fs));
1605 gtk_widget_destroy(GTK_WIDGET (fs));
1607 /* Save the directory name for future file dialogs. */
1608 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1609 set_last_open_dir(dirname);
1614 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1616 file_color_export_w = NULL;