2 * Dialog boxes for handling files
4 * $Id: file_dlg.c,v 1.102 2004/03/29 22:55:13 guy 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 fs = file_selection_new(label, FILE_SELECTION_SAVE);
117 /* If we've opened a file, start out by showing the files in the directory
118 in which that file resided. */
120 file_selection_set_current_folder(fs, last_open_dir);
122 OBJECT_SET_DATA(fs, PRINT_FILE_TE_KEY, file_te);
124 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
125 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
127 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
128 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
130 /* Call a handler when the file selection box is destroyed, so we can inform
131 our caller, if any, that it's been destroyed. */
132 SIGNAL_CONNECT(fs, "destroy", GTK_SIGNAL_FUNC(file_select_destroy_cb),
135 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
136 if (gtk_dialog_run(GTK_DIALOG(fs)) == GTK_RESPONSE_ACCEPT)
138 f_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
139 gtk_entry_set_text(GTK_ENTRY(file_te), f_name);
142 gtk_widget_destroy(fs);
144 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked",
145 file_select_ok_cb, fs);
147 /* Connect the cancel_button to destroy the widget */
148 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked",
149 file_select_cancel_cb, fs);
151 /* Catch the "key_press_event" signal in the window, so that we can catch
152 the ESC key being pressed and act as if the "Cancel" button had
154 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
160 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 4) || GTK_MAJOR_VERSION < 2
162 file_select_ok_cb(GtkWidget *w _U_, gpointer data)
166 f_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (data)));
168 /* Perhaps the user specified a directory instead of a file.
169 Check whether they did. */
170 if (test_for_directory(f_name) == EISDIR) {
171 /* It's a directory - set the file selection box to display it. */
172 set_last_open_dir(f_name);
174 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
179 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, PRINT_FILE_TE_KEY)),
181 gtk_widget_destroy(GTK_WIDGET(data));
187 file_select_cancel_cb(GtkWidget *w _U_, gpointer data)
189 gtk_widget_destroy(GTK_WIDGET(data));
194 file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te)
198 /* Get the widget that requested that we be popped up.
199 (It should arrange to destroy us if it's destroyed, so
200 that we don't get a pointer to a non-existent window here.) */
201 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
203 /* Tell it we no longer exist. */
204 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
206 /* Now nuke this window. */
207 gtk_grab_remove(GTK_WIDGET(win));
208 gtk_widget_destroy(GTK_WIDGET(win));
210 /* Give the focus to the file text entry widget so the user can just press
211 Return to print to the file. */
212 gtk_widget_grab_focus(file_te);
216 * Keep a static pointer to the current "Open Capture File" window, if
217 * any, so that if somebody tries to do "File:Open" while there's already
218 * an "Open Capture File" window up, we just pop up the existing one,
219 * rather than creating a new one.
221 static GtkWidget *file_open_w;
225 file_open_cmd(GtkWidget *w)
227 GtkWidget *main_vb, *filter_hbox, *filter_bt, *filter_te,
228 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
229 #if GTK_MAJOR_VERSION < 2
230 GtkAccelGroup *accel_group;
232 /* No Apply button, and "OK" just sets our text widget, it doesn't
233 activate it (i.e., it doesn't cause us to try to open the file). */
234 static construct_args_t args = {
235 "Ethereal: Read Filter",
240 if (file_open_w != NULL) {
241 /* There's already an "Open Capture File" dialog box; reactivate it. */
242 reactivate_window(file_open_w);
246 file_open_w = file_selection_new("Ethereal: Open Capture File",
247 FILE_SELECTION_OPEN);
248 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
250 #if GTK_MAJOR_VERSION < 2
251 /* Accelerator group for the accelerators (or, as they're called in
252 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
253 Ctrl+<key> is an accelerator). */
254 accel_group = gtk_accel_group_new();
255 gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
258 switch (prefs.gui_fileopen_style) {
260 case FO_STYLE_LAST_OPENED:
261 /* The user has specified that we should start out in the last directory
262 we looked in. If we've already opened a file, use its containing
263 directory, if we could determine it, as the directory, otherwise
264 use the "last opened" directory saved in the preferences file if
267 file_selection_set_current_folder(file_open_w, last_open_dir);
270 case FO_STYLE_SPECIFIED:
271 /* The user has specified that we should always start out in a
272 specified directory; if they've specified that directory,
273 start out by showing the files in that dir. */
274 if (prefs.gui_fileopen_dir[0] != '\0')
275 file_selection_set_current_folder(file_open_w, prefs.gui_fileopen_dir);
279 /* Container for each row of widgets */
280 main_vb = gtk_vbox_new(FALSE, 3);
281 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
282 file_selection_set_extra_widget(file_open_w, main_vb);
283 gtk_widget_show(main_vb);
285 filter_hbox = gtk_hbox_new(FALSE, 1);
286 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
287 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
288 gtk_widget_show(filter_hbox);
290 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
291 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
292 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
293 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
294 gtk_widget_show(filter_bt);
296 filter_te = gtk_entry_new();
297 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
298 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
299 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
300 gtk_widget_show(filter_te);
302 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
303 OBJECT_SET_DATA(file_open_w, E_RFILTER_TE_KEY, filter_te);
305 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
306 E_RFILTER_TE_KEY, filter_te);
309 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
310 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
311 g_resolv_flags & RESOLV_MAC);
312 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
313 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
314 OBJECT_SET_DATA(file_open_w,
315 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
317 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
318 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
320 gtk_widget_show(m_resolv_cb);
322 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
323 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
324 g_resolv_flags & RESOLV_NETWORK);
325 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
326 gtk_widget_show(n_resolv_cb);
327 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
328 OBJECT_SET_DATA(file_open_w, E_FILE_N_RESOLVE_KEY, n_resolv_cb);
330 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
331 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
334 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
335 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
336 g_resolv_flags & RESOLV_TRANSPORT);
337 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
338 gtk_widget_show(t_resolv_cb);
339 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
340 OBJECT_SET_DATA(file_open_w, E_FILE_T_RESOLVE_KEY, t_resolv_cb);
342 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
343 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
346 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
347 OBJECT_SET_DATA(file_open_w, E_DFILTER_TE_KEY,
348 OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
349 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
351 file_open_ok_cb(file_open_w, file_open_w);
353 else gtk_widget_destroy(file_open_w);
355 /* Connect the ok_button to file_open_ok_cb function and pass along a
356 pointer to the file selection box widget */
357 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
358 file_open_ok_cb, file_open_w);
360 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
361 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
363 /* Connect the cancel_button to destroy the widget */
364 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button,
365 "clicked", (GtkSignalFunc)gtk_widget_destroy,
368 /* Catch the "key_press_event" signal in the window, so that we can catch
369 the ESC key being pressed and act as if the "Cancel" button had
371 dlg_set_cancel(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
373 gtk_widget_show(file_open_w);
377 void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
381 /* save file first */
382 file_save_as_cmd(after_save_open_dialog, data);
388 case(ESD_BTN_CANCEL):
391 g_assert_not_reached();
396 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
399 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
400 /* user didn't saved his current file, ask him */
401 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
402 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
403 "If you open a new capture file without saving, your capture data will be discarded.");
404 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
406 /* unchanged file, just open a new one */
407 file_open_cmd(widget);
412 file_open_ok_cb(GtkWidget *w, gpointer fs) {
413 gchar *cf_name, *rfilter, *s;
414 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
415 dfilter_t *rfcode = NULL;
418 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
419 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
421 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
423 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
424 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
425 if (!dfilter_compile(rfilter, &rfcode)) {
426 bad_dfilter_alert_box(rfilter);
431 /* Perhaps the user specified a directory instead of a file.
432 Check whether they did. */
433 if (test_for_directory(cf_name) == EISDIR) {
434 /* It's a directory - set the file selection box to display that
435 directory, don't try to open the directory as a capture file. */
436 set_last_open_dir(cf_name);
438 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
442 /* Try to open the capture file. */
443 if ((err = cf_open(cf_name, FALSE, &cfile)) != 0) {
444 /* We couldn't open it; don't dismiss the open dialog box,
445 just leave it around so that the user can, after they
446 dismiss the alert box popped up for the open error,
449 dfilter_free(rfcode);
454 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
455 it closed the previous capture file, and thus destroyed any
456 previous read filter attached to "cf"). */
457 cfile.rfcode = rfcode;
459 /* Set the global resolving variable */
460 g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
461 m_resolv_cb = OBJECT_GET_DATA(w, E_FILE_M_RESOLVE_KEY);
462 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)) ? RESOLV_MAC : RESOLV_NONE;
463 n_resolv_cb = OBJECT_GET_DATA(w, E_FILE_N_RESOLVE_KEY);
464 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)) ? RESOLV_NETWORK : RESOLV_NONE;
465 t_resolv_cb = OBJECT_GET_DATA(w, E_FILE_T_RESOLVE_KEY);
466 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)) ? RESOLV_TRANSPORT : RESOLV_NONE;
468 /* We've crossed the Rubicon; get rid of the file selection box. */
469 gtk_widget_hide(GTK_WIDGET (fs));
470 gtk_widget_destroy(GTK_WIDGET (fs));
472 switch (cf_read(&cfile)) {
476 /* Just because we got an error, that doesn't mean we were unable
477 to read any of the file; we handle what we could get from the
482 /* The user bailed out of re-reading the capture file; the
483 capture file has been closed - just free the capture file name
484 string and return (without changing the last containing
490 /* Save the name of the containing directory specified in the path name,
491 if any; we can write over cf_name, which is a good thing, given that
492 "get_dirname()" does write over its argument. */
493 s = get_dirname(cf_name);
494 set_last_open_dir(s);
495 gtk_widget_grab_focus(packet_list);
501 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
503 /* Note that we no longer have a "Open Capture File" dialog box. */
507 void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
511 /* save file first */
512 file_save_as_cmd(after_save_close_file, NULL);
517 case(ESD_BTN_CANCEL):
520 g_assert_not_reached();
526 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
529 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
530 /* user didn't saved his current file, ask him */
531 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_YES_NO_CANCEL,
532 PRIMARY_TEXT_START "Save capture file before closing it?" PRIMARY_TEXT_END "\n\n"
533 "If you close without saving, your capture data will be discarded.");
535 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
537 /* unchanged file, just close it */
543 file_save_cmd_cb(GtkWidget *w, gpointer data) {
544 /* If the file's already been saved, do nothing. */
545 if (cfile.user_saved)
548 /* Do a "Save As". */
549 file_save_as_cmd_cb(w, data);
552 /* XXX - can we make these not be static? */
553 static packet_range_t range;
554 static gboolean color_marked;
556 static GtkWidget *captured_bt;
557 static GtkWidget *displayed_bt;
558 static GtkWidget *select_all_rb;
559 static GtkWidget *select_all_c_lb;
560 static GtkWidget *select_all_d_lb;
561 static GtkWidget *select_curr_rb;
562 static GtkWidget *select_curr_c_lb;
563 static GtkWidget *select_curr_d_lb;
564 static GtkWidget *select_marked_only_rb;
565 static GtkWidget *select_marked_only_c_lb;
566 static GtkWidget *select_marked_only_d_lb;
567 static GtkWidget *select_marked_range_rb;
568 static GtkWidget *select_marked_range_c_lb;
569 static GtkWidget *select_marked_range_d_lb;
570 static GtkWidget *select_user_range_rb;
571 static GtkWidget *select_user_range_c_lb;
572 static GtkWidget *select_user_range_d_lb;
573 static GtkWidget *select_user_range_entry;
574 static GtkWidget *cfmark_cb;
575 static GtkWidget *ft_om;
578 can_save_with_wiretap(int ft)
580 /* To save a file with Wiretap, Wiretap has to handle that format,
581 and its code to handle that format must be able to write a file
582 with this file's encapsulation type. */
583 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
587 file_set_save_dynamics(void) {
588 gboolean filtered_active;
589 gchar label_text[100];
593 filtered_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displayed_bt));
595 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(filetype));
597 gtk_widget_set_sensitive(select_all_c_lb, !filtered_active);
598 g_snprintf(label_text, sizeof(label_text), "%u", cfile.count);
599 gtk_label_set_text(GTK_LABEL(select_all_c_lb), label_text);
600 gtk_widget_set_sensitive(select_all_d_lb, filtered_active);
601 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_cnt);
603 gtk_label_set_text(GTK_LABEL(select_all_d_lb), label_text);
605 selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
606 /* XXX: how to update the radio button label but keep the mnemonic? */
607 /* g_snprintf(label_text, sizeof(label_text), "_Selected packet #%u only", selected_num);
608 gtk_label_set_text(GTK_LABEL(GTK_BIN(select_curr_rb)->child), label_text);*/
609 gtk_widget_set_sensitive(select_curr_rb, selected_num);
610 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
611 gtk_label_set_text(GTK_LABEL(select_curr_c_lb), label_text);
612 gtk_widget_set_sensitive(select_curr_c_lb, selected_num && !filtered_active);
613 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
614 gtk_label_set_text(GTK_LABEL(select_curr_d_lb), label_text);
615 gtk_widget_set_sensitive(select_curr_d_lb, selected_num && filtered_active);
617 gtk_widget_set_sensitive(select_marked_only_rb, cfile.marked_count);
618 g_snprintf(label_text, sizeof(label_text), "%u", cfile.marked_count);
619 gtk_label_set_text(GTK_LABEL(select_marked_only_c_lb), label_text);
620 gtk_widget_set_sensitive(select_marked_only_c_lb, cfile.marked_count && !filtered_active);
621 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_marked_cnt);
622 gtk_label_set_text(GTK_LABEL(select_marked_only_d_lb), label_text);
623 gtk_widget_set_sensitive(select_marked_only_d_lb, range.displayed_marked_cnt && filtered_active);
625 gtk_widget_set_sensitive(select_marked_range_rb, range.mark_range_cnt);
626 g_snprintf(label_text, sizeof(label_text), "%u", range.mark_range_cnt);
627 gtk_label_set_text(GTK_LABEL(select_marked_range_c_lb), label_text);
628 gtk_widget_set_sensitive(select_marked_range_c_lb, range.mark_range_cnt && !filtered_active);
629 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_mark_range_cnt);
630 gtk_label_set_text(GTK_LABEL(select_marked_range_d_lb), label_text);
631 gtk_widget_set_sensitive(select_marked_range_d_lb, range.displayed_mark_range_cnt && filtered_active);
633 gtk_widget_set_sensitive(select_user_range_rb, TRUE);
634 g_snprintf(label_text, sizeof(label_text), "%u", range.user_range_cnt);
635 gtk_label_set_text(GTK_LABEL(select_user_range_c_lb), label_text);
636 gtk_widget_set_sensitive(select_user_range_c_lb, !filtered_active);
637 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_user_range_cnt);
638 gtk_label_set_text(GTK_LABEL(select_user_range_d_lb), label_text);
639 gtk_widget_set_sensitive(select_user_range_d_lb, filtered_active);
642 /* Generate a list of the file types we can save this file as.
644 "filetype" is the type it has now.
646 "encap" is the encapsulation for its packets (which could be
647 "unknown" or "per-packet").
649 "filtered" is TRUE if we're to save only the packets that passed
650 the display filter (in which case we have to save it using Wiretap)
651 and FALSE if we're to save the entire file (in which case, if we're
652 saving it in the type it has already, we can just copy it).
654 The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
657 set_file_type_list(GtkWidget *option_menu)
659 GtkWidget *ft_menu, *ft_menu_item;
662 guint item_to_select;
664 /* Default to the first supported file type, if the file's current
665 type isn't supported. */
668 ft_menu = gtk_menu_new();
670 /* Check all file types. */
672 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
673 if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
674 /* not all unfiltered packets or a different file type. We have to use Wiretap. */
675 if (!can_save_with_wiretap(ft))
676 continue; /* We can't. */
679 /* OK, we can write it out in this type. */
680 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
681 if (ft == filetype) {
682 /* Default to the same format as the file, if it's supported. */
683 item_to_select = index;
685 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
686 GINT_TO_POINTER(ft));
687 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
688 gtk_widget_show(ft_menu_item);
692 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
693 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
697 select_file_type_cb(GtkWidget *w _U_, gpointer data)
699 int new_filetype = GPOINTER_TO_INT(data);
701 if (filetype != new_filetype) {
702 /* We can select only the filtered or marked packets to be saved if we can
703 use Wiretap to save the file. */
704 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(new_filetype));
705 filetype = new_filetype;
706 file_set_save_marked_sensitive();
711 toggle_captured_cb(GtkWidget *widget, gpointer data _U_)
713 /* is the button now active? */
714 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
715 /* They changed the state of the "captured" button. */
716 range.process_filtered = FALSE;
717 /* XXX: the following line fails, I have no idea why */
718 /* set_file_type_list(ft_om);*/
720 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
721 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
723 file_set_save_dynamics();
728 toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
730 /* is the button now active? */
731 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
732 range.process_filtered = TRUE;
733 set_file_type_list(ft_om);
735 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), FALSE);
736 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), TRUE);
738 file_set_save_dynamics();
743 toggle_select_all(GtkWidget *widget, gpointer data _U_)
745 /* is the button now active? */
746 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
747 range.process = range_process_all;
748 set_file_type_list(ft_om);
749 file_set_save_dynamics();
754 toggle_select_selected(GtkWidget *widget, gpointer data _U_)
756 /* is the button now active? */
757 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
758 range.process = range_process_selected;
759 set_file_type_list(ft_om);
760 file_set_save_dynamics();
765 toggle_select_marked_only(GtkWidget *widget, gpointer data _U_)
767 /* is the button now active? */
768 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
769 range.process = range_process_marked;
770 set_file_type_list(ft_om);
771 file_set_save_dynamics();
776 toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
778 /* is the button now active? */
779 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
780 range.process = range_process_marked_range;
781 set_file_type_list(ft_om);
782 file_set_save_dynamics();
787 toggle_select_user_range(GtkWidget *widget, gpointer data _U_)
789 /* is the button now active? */
790 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
791 range.process = range_process_user_range;
792 set_file_type_list(ft_om);
793 file_set_save_dynamics();
796 /* Make the entry widget sensitive or insensitive */
797 gtk_widget_set_sensitive(select_user_range_entry, range.process == range_process_user_range);
799 /* When selecting user specified range, then focus on the entry */
800 if (range.process == range_process_user_range)
801 gtk_widget_grab_focus(select_user_range_entry);
806 range_entry(GtkWidget *entry)
808 const gchar *entry_text;
810 entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
811 packet_range_convert_str(&range, entry_text);
812 file_set_save_dynamics();
816 * Set the "Save only marked packets" toggle button as appropriate for
817 * the current output file type and count of marked packets.
819 * Called when the "Save As..." dialog box is created and when either
820 * the file type or the marked count changes.
823 file_set_save_marked_sensitive(void)
825 if (file_save_as_w == NULL) {
826 /* We don't currently have a "Save As..." dialog box up. */
830 /* We can request that only the marked packets be saved only if we
831 can use Wiretap to save the file and if there *are* marked packets. */
832 if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
833 gtk_widget_set_sensitive(select_marked_only_rb, TRUE);
834 gtk_widget_set_sensitive(select_marked_range_rb, TRUE);
837 /* Force the "Save only marked packets" toggle to "false", turn
838 off the flag it controls, and update the list of types we can
840 range.process = range_process_all;
841 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_only_rb), FALSE);
842 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_range_rb), FALSE);
843 set_file_type_list(ft_om);
844 gtk_widget_set_sensitive(select_marked_only_rb, FALSE);
845 gtk_widget_set_sensitive(select_marked_range_rb, FALSE);
849 action_after_save_e action_after_save_g;
850 gpointer action_after_save_data_g;
854 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
856 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *range_tb;
857 GtkTooltips *tooltips;
859 #if GTK_MAJOR_VERSION < 2
860 GtkAccelGroup *accel_group;
863 if (file_save_as_w != NULL) {
864 /* There's already an "Save Capture File As" dialog box; reactivate it. */
865 reactivate_window(file_save_as_w);
869 /* Default to saving all packets, in the file's current format. */
870 filetype = cfile.cd_t;
872 /* init the packet range */
873 packet_range_init(&range);
875 /* Enable tooltips */
876 tooltips = gtk_tooltips_new();
878 /* build the file selection */
879 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As",
880 FILE_SELECTION_SAVE);
881 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
883 /* as the dialog might already be gone, when using this values, we cannot
884 * set data to the dialog object, but keep global values */
885 action_after_save_g = action_after_save;
886 action_after_save_data_g = action_after_save_data;
888 #if GTK_MAJOR_VERSION < 2
889 accel_group = gtk_accel_group_new();
890 gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
893 /* If we've opened a file, start out by showing the files in the directory
894 in which that file resided. */
896 file_selection_set_current_folder(file_save_as_w, last_open_dir);
898 /* Container for each row of widgets */
900 main_vb = gtk_vbox_new(FALSE, 5);
901 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
902 file_selection_set_extra_widget(file_save_as_w, main_vb);
903 gtk_widget_show(main_vb);
905 /*** Packet Range frame ***/
906 range_fr = gtk_frame_new("Packet Range");
907 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
908 gtk_widget_show(range_fr);
911 range_tb = gtk_table_new(7, 3, FALSE);
912 gtk_container_border_width(GTK_CONTAINER(range_tb), 5);
913 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
914 gtk_widget_show(range_tb);
916 /* captured button */
917 captured_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Captured", accel_group);
918 gtk_table_attach_defaults(GTK_TABLE(range_tb), captured_bt, 1, 2, 0, 1);
919 SIGNAL_CONNECT(captured_bt, "toggled", toggle_captured_cb, NULL);
920 gtk_tooltips_set_tip (tooltips,captured_bt,("Process all the below chosen packets"), NULL);
921 gtk_widget_show(captured_bt);
923 /* displayed button */
924 displayed_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Displayed", accel_group);
925 gtk_table_attach_defaults(GTK_TABLE(range_tb), displayed_bt, 2, 3, 0, 1);
926 SIGNAL_CONNECT(displayed_bt, "toggled", toggle_filtered_cb, NULL);
927 gtk_tooltips_set_tip (tooltips,displayed_bt,("Process only the below chosen packets, which also passes the current display filter"), NULL);
928 gtk_widget_show(displayed_bt);
931 /* Process all packets */
932 select_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "_All packets", accel_group);
933 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 1, 2);
934 gtk_tooltips_set_tip (tooltips,select_all_rb,("Process all packets"), NULL);
935 SIGNAL_CONNECT(select_all_rb, "toggled", toggle_select_all, NULL);
936 gtk_widget_show(select_all_rb);
938 select_all_c_lb = gtk_label_new("?");
939 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_c_lb, 1, 2, 1, 2);
940 gtk_widget_show(select_all_c_lb);
941 select_all_d_lb = gtk_label_new("?");
942 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_d_lb, 2, 3, 1, 2);
943 gtk_widget_show(select_all_d_lb);
946 /* Process currently selected */
947 select_curr_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Selected packet only", accel_group);
948 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_rb, 0, 1, 2, 3);
949 gtk_tooltips_set_tip (tooltips,select_curr_rb,("Process the currently selected packet only"), NULL);
950 SIGNAL_CONNECT(select_curr_rb, "toggled", toggle_select_selected, NULL);
951 gtk_widget_show(select_curr_rb);
953 select_curr_c_lb = gtk_label_new("?");
954 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_c_lb, 1, 2, 2, 3);
955 gtk_widget_show(select_curr_c_lb);
956 select_curr_d_lb = gtk_label_new("?");
957 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_d_lb, 2, 3, 2, 3);
958 gtk_widget_show(select_curr_d_lb);
961 /* Process marked packets */
962 select_marked_only_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Marked packets only", accel_group);
963 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_rb, 0, 1, 3, 4);
964 gtk_tooltips_set_tip (tooltips,select_marked_only_rb,("Process marked packets only"), NULL);
965 SIGNAL_CONNECT(select_marked_only_rb, "toggled", toggle_select_marked_only, NULL);
966 gtk_widget_show(select_marked_only_rb);
968 select_marked_only_c_lb = gtk_label_new("?");
969 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_c_lb, 1, 2, 3, 4);
970 gtk_widget_show(select_marked_only_c_lb);
971 select_marked_only_d_lb = gtk_label_new("?");
972 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_d_lb, 2, 3, 3, 4);
973 gtk_widget_show(select_marked_only_d_lb);
976 /* Process packet range between first and last packet */
977 select_marked_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "From first _to last marked packet", accel_group);
978 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_rb, 0, 1, 4, 5);
979 gtk_tooltips_set_tip (tooltips,select_marked_range_rb,("Process all packets between the first and last marker"), NULL);
980 SIGNAL_CONNECT(select_marked_range_rb, "toggled", toggle_select_marked_range, NULL);
981 gtk_widget_show(select_marked_range_rb);
983 select_marked_range_c_lb = gtk_label_new("?");
984 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_c_lb, 1, 2, 4, 5);
985 gtk_widget_show(select_marked_range_c_lb);
986 select_marked_range_d_lb = gtk_label_new("?");
987 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_d_lb, 2, 3, 4, 5);
988 gtk_widget_show(select_marked_range_d_lb);
991 /* Process a user specified provided packet range : -10,30,40-70,80- */
992 select_user_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "Specify a packet _range:", accel_group);
993 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_rb, 0, 1, 5, 6);
994 gtk_tooltips_set_tip (tooltips,select_user_range_rb,("Process a specified packet range"), NULL);
995 SIGNAL_CONNECT(select_user_range_rb, "toggled", toggle_select_user_range, NULL);
996 gtk_widget_show(select_user_range_rb);
998 select_user_range_c_lb = gtk_label_new("?");
999 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_c_lb, 1, 2, 5, 6);
1000 gtk_widget_show(select_user_range_c_lb);
1001 select_user_range_d_lb = gtk_label_new("?");
1002 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_d_lb, 2, 3, 5, 6);
1003 gtk_widget_show(select_user_range_d_lb);
1006 /* The entry part */
1007 select_user_range_entry = gtk_entry_new();
1008 gtk_entry_set_max_length (GTK_ENTRY (select_user_range_entry), 254);
1009 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_entry, 0, 1, 6, 7);
1010 gtk_tooltips_set_tip (tooltips,select_user_range_entry,
1011 ("Specify a range of packet numbers : \nExample : 1-10,18,25-100,332-"), NULL);
1012 SIGNAL_CONNECT(select_user_range_entry,"changed", range_entry, select_user_range_entry);
1013 gtk_widget_set_sensitive(select_user_range_entry, FALSE);
1014 gtk_widget_show(select_user_range_entry);
1016 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
1017 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
1018 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb), TRUE);
1021 ft_hb = gtk_hbox_new(FALSE, 3);
1022 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1023 gtk_widget_show(ft_hb);
1025 ft_lb = gtk_label_new("File type:");
1026 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1027 gtk_widget_show(ft_lb);
1029 ft_om = gtk_option_menu_new();
1031 /* Generate the list of file types we can save. */
1032 set_file_type_list(ft_om);
1033 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1034 gtk_widget_show(ft_om);
1037 * Set the sensitivity of the "Save only marked packets" toggle
1040 * This has to be done after we create the file type menu option,
1041 * as the routine that sets it also sets that menu.
1043 file_set_save_marked_sensitive();
1045 /* dynamic values in the range frame */
1046 file_set_save_dynamics();
1048 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1049 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT)
1051 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1053 else gtk_widget_destroy(file_save_as_w);
1055 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
1056 pointer to the file selection box widget */
1057 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_save_as_w)->ok_button, "clicked",
1058 file_save_as_ok_cb, file_save_as_w);
1060 /* Connect the cancel_button to destroy the widget */
1061 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
1062 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1065 /* Catch the "key_press_event" signal in the window, so that we can catch
1066 the ESC key being pressed and act as if the "Cancel" button had
1068 dlg_set_cancel(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
1070 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
1072 gtk_widget_show(file_save_as_w);
1077 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1079 file_save_as_cmd(after_save_no_action, NULL);
1083 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1087 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1088 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1090 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1093 /* Perhaps the user specified a directory instead of a file.
1094 Check whether they did. */
1095 if (test_for_directory(cf_name) == EISDIR) {
1096 /* It's a directory - set the file selection box to display that
1097 directory, and leave the selection box displayed. */
1098 set_last_open_dir(cf_name);
1100 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1104 /* don't show the dialog while saving */
1105 gtk_widget_hide(GTK_WIDGET (fs));
1107 /* Write out the packets (all, or only the ones from the current
1108 range) to the file with the specified name. */
1109 if (! cf_save(cf_name, &cfile, &range, filetype)) {
1110 /* The write failed; don't dismiss the open dialog box,
1111 just leave it around so that the user can, after they
1112 dismiss the alert box popped up for the error, try again. */
1114 gtk_widget_show(GTK_WIDGET (fs));
1118 /* The write succeeded; get rid of the file selection box. */
1119 /* cf_save might already closed our dialog! */
1121 gtk_widget_destroy(GTK_WIDGET (fs));
1123 /* Save the directory name for future file dialogs. */
1124 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1125 set_last_open_dir(dirname);
1128 /* we have finished saving, do we have pending things to do? */
1129 switch(action_after_save_g) {
1130 case(after_save_no_action):
1132 case(after_save_open_dialog):
1133 file_open_cmd(action_after_save_data_g);
1135 case(after_save_open_recent_file):
1136 menu_open_recent_file_cmd(action_after_save_data_g);
1138 case(after_save_open_dnd_file):
1139 dnd_open_file_cmd(action_after_save_data_g);
1142 case(after_save_capture_dialog):
1146 case(after_save_close_file):
1149 case(after_save_exit):
1153 g_assert_not_reached();
1156 action_after_save_g = after_save_no_action;
1160 file_save_as_destroy(void)
1163 gtk_widget_destroy(file_save_as_w);
1167 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1169 /* Note that we no longer have a "Save Capture File As" dialog box. */
1170 file_save_as_w = NULL;
1173 /* Reload a file using the current read and display filters */
1175 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1177 gboolean is_tempfile;
1179 /* If the file could be opened, "cf_open()" calls "cf_close()"
1180 to get rid of state for the old capture file before filling in state
1181 for the new capture file. "cf_close()" will remove the file if
1182 it's a temporary file; we don't want that to happen (for one thing,
1183 it'd prevent subsequent reopens from working). Remember whether it's
1184 a temporary file, mark it as not being a temporary file, and then
1185 reopen it as the type of file it was.
1187 Also, "cf_close()" will free "cfile.filename", so we must make
1188 a copy of it first. */
1189 filename = g_strdup(cfile.filename);
1190 is_tempfile = cfile.is_tempfile;
1191 cfile.is_tempfile = FALSE;
1192 if (cf_open(filename, is_tempfile, &cfile) == 0) {
1193 switch (cf_read(&cfile)) {
1197 /* Just because we got an error, that doesn't mean we were unable
1198 to read any of the file; we handle what we could get from the
1203 /* The user bailed out of re-reading the capture file; the
1204 capture file has been closed - just free the capture file name
1205 string and return (without changing the last containing
1211 /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
1212 Instead, the file was left open, so we should restore "cfile.is_tempfile"
1215 XXX - change the menu? Presumably "cf_open()" will do that;
1216 make sure it does! */
1217 cfile.is_tempfile = is_tempfile;
1219 /* "cf_open()" made a copy of the file name we handed it, so
1220 we should free up our copy. */
1224 /******************** Color Filters *********************************/
1226 * Keep a static pointer to the current "Color Export" window, if
1227 * any, so that if somebody tries to do "Export"
1228 * while there's already a "Color Export" window up, we just pop
1229 * up the existing one, rather than creating a new one.
1231 static GtkWidget *file_color_import_w;
1233 /* sets the file path to the global color filter file.
1234 WARNING: called by both the import and the export dialog.
1237 color_global_cb(GtkWidget *widget _U_, gpointer data)
1239 GtkWidget *fs_widget = data;
1242 /* decide what file to open (from dfilter code) */
1243 path = get_datafile_path("colorfilters");
1245 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1246 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1248 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs_widget), path);
1250 g_free((gchar *)path);
1253 /* Import color filters */
1255 file_color_import_cmd_cb(GtkWidget *w _U_, gpointer data)
1257 GtkWidget *main_vb, *cfglobal_but;
1258 #if GTK_MAJOR_VERSION < 2
1259 GtkAccelGroup *accel_group;
1261 /* No Apply button, and "OK" just sets our text widget, it doesn't
1262 activate it (i.e., it doesn't cause us to try to open the file). */
1264 if (file_color_import_w != NULL) {
1265 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1266 reactivate_window(file_color_import_w);
1270 file_color_import_w = file_selection_new("Ethereal: Import Color Filters",
1271 FILE_SELECTION_OPEN);
1272 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1274 #if GTK_MAJOR_VERSION < 2
1275 /* Accelerator group for the accelerators (or, as they're called in
1276 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
1277 Ctrl+<key> is an accelerator). */
1278 accel_group = gtk_accel_group_new();
1279 gtk_window_add_accel_group(GTK_WINDOW(file_color_import_w), accel_group);
1282 /* If we've opened a file, start out by showing the files in the directory
1283 in which that file resided. */
1285 file_selection_set_current_folder(file_color_import_w, last_open_dir);
1287 /* Container for each row of widgets */
1288 main_vb = gtk_vbox_new(FALSE, 3);
1289 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1290 file_selection_set_extra_widget(file_color_import_w, main_vb);
1291 gtk_widget_show(main_vb);
1294 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1295 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1296 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1297 gtk_widget_show(cfglobal_but);
1299 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1300 OBJECT_SET_DATA(file_color_import_w, ARGUMENT_CL, data);
1302 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1304 file_color_import_ok_cb(file_color_import_w, file_color_import_w);
1306 else gtk_widget_destroy(file_color_import_w);
1308 /* Connect the ok_button to file_open_ok_cb function and pass along a
1309 pointer to the file selection box widget */
1310 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1311 file_color_import_ok_cb, file_color_import_w);
1313 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_color_import_w)->ok_button,
1316 /* Connect the cancel_button to destroy the widget */
1317 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_import_w)->cancel_button,
1318 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1319 file_color_import_w);
1321 /* Catch the "key_press_event" signal in the window, so that we can catch
1322 the ESC key being pressed and act as if the "Cancel" button had
1324 dlg_set_cancel(file_color_import_w, GTK_FILE_SELECTION(file_color_import_w)->cancel_button);
1326 gtk_widget_show(file_color_import_w);
1331 file_color_import_ok_cb(GtkWidget *w, gpointer fs) {
1335 argument = OBJECT_GET_DATA(w, ARGUMENT_CL); /* to be passed back into read_other_filters */
1337 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1338 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1340 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1342 /* Perhaps the user specified a directory instead of a file.
1343 Check whether they did. */
1344 if (test_for_directory(cf_name) == EISDIR) {
1345 /* It's a directory - set the file selection box to display that
1346 directory, don't try to open the directory as a capture file. */
1347 set_last_open_dir(cf_name);
1349 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1353 /* Try to open the capture file. */
1355 if (!read_other_filters(cf_name, argument)) {
1356 /* We couldn't open it; don't dismiss the open dialog box,
1357 just leave it around so that the user can, after they
1358 dismiss the alert box popped up for the open error,
1364 /* We've crossed the Rubicon; get rid of the file selection box. */
1365 gtk_widget_hide(GTK_WIDGET (fs));
1366 gtk_widget_destroy(GTK_WIDGET (fs));
1368 /* Save the name of the containing directory specified in the path name,
1369 if any; we can write over cf_name, which is a good thing, given that
1370 "get_dirname()" does write over its argument. */
1371 s = get_dirname(cf_name);
1372 set_last_open_dir(s);
1373 gtk_widget_grab_focus(packet_list);
1379 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1381 /* Note that we no longer have a "Open Capture File" dialog box. */
1382 file_color_import_w = NULL;
1385 static GtkWidget *file_color_export_w;
1387 * Set the "Export only marked filters" toggle button as appropriate for
1388 * the current output file type and count of marked filters.
1390 * Called when the "Export" dialog box is created and when the marked
1394 color_set_export_marked_sensitive(GtkWidget * cfmark_cb)
1396 if (file_color_export_w == NULL) {
1397 /* We don't currently have an "Export" dialog box up. */
1401 /* We can request that only the marked filters be saved only if
1402 there *are* marked filters. */
1403 if (color_marked_count() != 0)
1404 gtk_widget_set_sensitive(cfmark_cb, TRUE);
1406 /* Force the "Export only marked filters" toggle to "false", turn
1407 off the flag it controls. */
1408 color_marked = FALSE;
1409 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1410 gtk_widget_set_sensitive(cfmark_cb, FALSE);
1415 color_toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
1417 color_marked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1421 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1423 GtkWidget *main_vb, *cfglobal_but;
1425 if (file_color_export_w != NULL) {
1426 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1427 reactivate_window(file_color_export_w);
1431 /* Default to saving all packets, in the file's current format. */
1432 color_marked = FALSE;
1433 filetype = cfile.cd_t;
1435 file_color_export_w = file_selection_new("Ethereal: Export Color Filters",
1436 FILE_SELECTION_SAVE);
1437 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1439 /* If we've opened a file, start out by showing the files in the directory
1440 in which that file resided. */
1442 file_selection_set_current_folder(file_color_export_w, last_open_dir);
1444 /* Container for each row of widgets */
1445 main_vb = gtk_vbox_new(FALSE, 3);
1446 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1447 file_selection_set_extra_widget(file_color_export_w, main_vb);
1448 gtk_widget_show(main_vb);
1450 cfmark_cb = gtk_check_button_new_with_label("Export only marked filters");
1451 gtk_container_add(GTK_CONTAINER(main_vb), cfmark_cb);
1452 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1453 SIGNAL_CONNECT(cfmark_cb, "toggled", color_toggle_marked_cb, NULL);
1454 gtk_widget_show(cfmark_cb);
1455 color_set_export_marked_sensitive(cfmark_cb);
1457 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1458 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1459 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1460 gtk_widget_show(cfglobal_but);
1462 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1463 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1465 file_color_export_ok_cb(file_color_export_w, file_color_export_w);
1467 else gtk_widget_destroy(file_color_export_w);
1469 /* Connect the ok_button to file_export_ok_cb function and pass along a
1470 pointer to the file selection box widget */
1471 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_color_export_w)->ok_button, "clicked",
1472 file_color_export_ok_cb, file_color_export_w);
1474 /* Connect the cancel_button to destroy the widget */
1475 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_export_w)->cancel_button,
1476 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1477 file_color_export_w);
1479 /* Catch the "key_press_event" signal in the window, so that we can catch
1480 the ESC key being pressed and act as if the "Cancel" button had
1482 dlg_set_cancel(file_color_export_w, GTK_FILE_SELECTION(file_color_export_w)->cancel_button);
1484 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1486 gtk_widget_show(file_color_export_w);
1491 file_color_export_ok_cb(GtkWidget *w _U_, gpointer fs) {
1495 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1496 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1498 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1501 /* Perhaps the user specified a directory instead of a file.
1502 Check whether they did. */
1503 if (test_for_directory(cf_name) == EISDIR) {
1504 /* It's a directory - set the file selection box to display that
1505 directory, and leave the selection box displayed. */
1506 set_last_open_dir(cf_name);
1508 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1512 /* Write out the filters (all, or only the ones that are currently
1513 displayed or marked) to the file with the specified name. */
1515 if (!write_other_filters(cf_name, color_marked))
1517 /* The write failed; don't dismiss the open dialog box,
1518 just leave it around so that the user can, after they
1519 dismiss the alert box popped up for the error, try again. */
1525 /* The write succeeded; get rid of the file selection box. */
1526 gtk_widget_hide(GTK_WIDGET (fs));
1527 gtk_widget_destroy(GTK_WIDGET (fs));
1529 /* Save the directory name for future file dialogs. */
1530 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1531 set_last_open_dir(dirname);
1536 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1538 file_color_export_w = NULL;