2 * Dialog boxes for handling files
4 * $Id: file_dlg.c,v 1.90 2004/01/31 18:32:36 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 "simple_dialog.h"
43 #include "dlg_utils.h"
45 #include "compat_macros.h"
48 #include "../ui_util.h"
49 #include "gtk/color_filters.h"
50 #include "gtk/color_dlg.h"
52 #include "capture_dlg.h"
56 static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
57 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
58 static void select_file_type_cb(GtkWidget *w, gpointer data);
59 static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
60 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
61 static void file_color_import_ok_cb(GtkWidget *w, GtkFileSelection *fs);
62 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
63 static void file_color_export_ok_cb(GtkWidget *w, GtkFileSelection *fs);
64 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
65 static void file_select_ok_cb(GtkWidget *w, gpointer data);
66 static void file_select_cancel_cb(GtkWidget *w, gpointer data);
67 static void file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te);
68 static void toggle_captured_cb(GtkWidget *widget, gpointer data _U_);
70 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
71 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
72 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
74 #define ARGUMENT_CL "argument_cl"
77 * Keep a static pointer to the current "Save Capture File As" window, if
78 * any, so that if somebody tries to do "File:Save" or "File:Save As"
79 * while there's already a "Save Capture File As" window up, we just pop
80 * up the existing one, rather than creating a new one.
82 static GtkWidget *file_save_as_w;
85 * A generic select_file_cb routine that is intended to be connected to
86 * a Browse button on other dialog boxes. This allows the user to browse
87 * for a file and select it. We fill in the text_entry that is asssociated
88 * with the button that invoked us.
90 * We display the window label specified in our args.
93 select_file_cb(GtkWidget *file_bt, const char *label)
95 GtkWidget *caller = gtk_widget_get_toplevel(file_bt);
96 GtkWidget *fs, *file_te;
98 /* Has a file selection dialog box already been opened for that top-level
100 fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
101 file_te = OBJECT_GET_DATA(file_bt, E_FILE_TE_PTR_KEY);
103 /* Yes. Just re-activate that dialog box. */
104 reactivate_window(fs);
108 fs = file_selection_new (label);
110 /* If we've opened a file, start out by showing the files in the directory
111 in which that file resided. */
113 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
115 OBJECT_SET_DATA(fs, PRINT_FILE_TE_KEY, file_te);
117 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
118 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
120 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
121 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
123 /* Call a handler when the file selection box is destroyed, so we can inform
124 our caller, if any, that it's been destroyed. */
125 SIGNAL_CONNECT(fs, "destroy", GTK_SIGNAL_FUNC(file_select_destroy_cb),
128 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked",
129 file_select_ok_cb, fs);
131 /* Connect the cancel_button to destroy the widget */
132 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked",
133 file_select_cancel_cb, fs);
135 /* Catch the "key_press_event" signal in the window, so that we can catch
136 the ESC key being pressed and act as if the "Cancel" button had
138 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
144 file_select_ok_cb(GtkWidget *w _U_, gpointer data)
148 f_name = g_strdup(gtk_file_selection_get_filename(
149 GTK_FILE_SELECTION (data)));
151 /* Perhaps the user specified a directory instead of a file.
152 Check whether they did. */
153 if (test_for_directory(f_name) == EISDIR) {
154 /* It's a directory - set the file selection box to display it. */
155 set_last_open_dir(f_name);
157 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
162 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, PRINT_FILE_TE_KEY)),
164 gtk_widget_destroy(GTK_WIDGET(data));
170 file_select_cancel_cb(GtkWidget *w _U_, gpointer data)
172 gtk_widget_destroy(GTK_WIDGET(data));
176 file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te)
180 /* Get the widget that requested that we be popped up.
181 (It should arrange to destroy us if it's destroyed, so
182 that we don't get a pointer to a non-existent window here.) */
183 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
185 /* Tell it we no longer exist. */
186 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
188 /* Now nuke this window. */
189 gtk_grab_remove(GTK_WIDGET(win));
190 gtk_widget_destroy(GTK_WIDGET(win));
192 /* Give the focus to the file text entry widget so the user can just press
193 Return to print to the file. */
194 gtk_widget_grab_focus(file_te);
198 * Keep a static pointer to the current "Open Capture File" window, if
199 * any, so that if somebody tries to do "File:Open" while there's already
200 * an "Open Capture File" window up, we just pop up the existing one,
201 * rather than creating a new one.
203 static GtkWidget *file_open_w;
207 file_open_cmd(GtkWidget *w)
209 GtkWidget *main_vb, *filter_hbox, *filter_bt, *filter_te,
210 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
211 #if GTK_MAJOR_VERSION < 2
212 GtkAccelGroup *accel_group;
214 /* No Apply button, and "OK" just sets our text widget, it doesn't
215 activate it (i.e., it doesn't cause us to try to open the file). */
216 static construct_args_t args = {
217 "Ethereal: Read Filter",
222 if (file_open_w != NULL) {
223 /* There's already an "Open Capture File" dialog box; reactivate it. */
224 reactivate_window(file_open_w);
228 file_open_w = file_selection_new ("Ethereal: Open Capture File");
229 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
231 #if GTK_MAJOR_VERSION < 2
232 /* Accelerator group for the accelerators (or, as they're called in
233 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
234 Ctrl+<key> is an accelerator). */
235 accel_group = gtk_accel_group_new();
236 gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
239 switch (prefs.gui_fileopen_style) {
241 case FO_STYLE_LAST_OPENED:
242 /* The user has specified that we should start out in the last directory
243 we looked in. If we've already opened a file, use its containing
244 directory, if we could determine it, as the directory, otherwise
245 use the "last opened" directory saved in the preferences file if
248 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
252 if (prefs.gui_fileopen_remembered_dir != NULL) {
253 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
254 prefs.gui_fileopen_remembered_dir);
259 case FO_STYLE_SPECIFIED:
260 /* The user has specified that we should always start out in a
261 specified directory; if they've specified that directory,
262 start out by showing the files in that dir. */
263 if (prefs.gui_fileopen_dir[0] != '\0') {
264 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
265 prefs.gui_fileopen_dir);
270 /* Container for each row of widgets */
271 main_vb = gtk_vbox_new(FALSE, 3);
272 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
273 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_open_w)->action_area),
274 main_vb, FALSE, FALSE, 0);
275 gtk_widget_show(main_vb);
277 filter_hbox = gtk_hbox_new(FALSE, 1);
278 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
279 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
280 gtk_widget_show(filter_hbox);
282 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
283 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
284 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
285 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
286 gtk_widget_show(filter_bt);
288 filter_te = gtk_entry_new();
289 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
290 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
291 gtk_widget_show(filter_te);
293 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
294 E_RFILTER_TE_KEY, filter_te);
296 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
297 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
298 g_resolv_flags & RESOLV_MAC);
299 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
300 gtk_widget_show(m_resolv_cb);
301 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
302 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
304 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
305 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
306 g_resolv_flags & RESOLV_NETWORK);
307 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
308 gtk_widget_show(n_resolv_cb);
309 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
310 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
312 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
313 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
314 g_resolv_flags & RESOLV_TRANSPORT);
315 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
316 gtk_widget_show(t_resolv_cb);
317 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
318 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
320 /* Connect the ok_button to file_open_ok_cb function and pass along a
321 pointer to the file selection box widget */
322 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
323 file_open_ok_cb, file_open_w);
325 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
326 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
328 /* Connect the cancel_button to destroy the widget */
329 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button,
330 "clicked", (GtkSignalFunc)gtk_widget_destroy,
333 /* Catch the "key_press_event" signal in the window, so that we can catch
334 the ESC key being pressed and act as if the "Cancel" button had
336 dlg_set_cancel(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
338 gtk_widget_show(file_open_w);
341 void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
345 /* save file first */
346 file_save_as_cmd(after_save_open_dialog, data);
351 case(ESD_BTN_CANCEL):
354 g_assert_not_reached();
359 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
362 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
363 /* user didn't saved his current file, ask him */
364 dialog = simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL,
365 ESD_BTN_YES | ESD_BTN_NO | ESD_BTN_CANCEL,
366 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
367 "If you open a new capture file without saving, your capture data will be discarded.");
368 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
370 /* unchanged file, just open a new one */
371 file_open_cmd(widget);
376 file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
377 gchar *cf_name, *rfilter, *s;
378 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
379 dfilter_t *rfcode = NULL;
382 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
383 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
384 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
385 if (!dfilter_compile(rfilter, &rfcode)) {
387 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, dfilter_error_msg);
391 /* Perhaps the user specified a directory instead of a file.
392 Check whether they did. */
393 if (test_for_directory(cf_name) == EISDIR) {
394 /* It's a directory - set the file selection box to display that
395 directory, don't try to open the directory as a capture file. */
396 set_last_open_dir(cf_name);
398 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
402 /* Try to open the capture file. */
403 if ((err = cf_open(cf_name, FALSE, &cfile)) != 0) {
404 /* We couldn't open it; don't dismiss the open dialog box,
405 just leave it around so that the user can, after they
406 dismiss the alert box popped up for the open error,
409 dfilter_free(rfcode);
414 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
415 it closed the previous capture file, and thus destroyed any
416 previous read filter attached to "cf"). */
417 cfile.rfcode = rfcode;
419 /* Set the global resolving variable */
420 g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
421 m_resolv_cb = OBJECT_GET_DATA(w, E_FILE_M_RESOLVE_KEY);
422 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)) ? RESOLV_MAC : RESOLV_NONE;
423 n_resolv_cb = OBJECT_GET_DATA(w, E_FILE_N_RESOLVE_KEY);
424 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)) ? RESOLV_NETWORK : RESOLV_NONE;
425 t_resolv_cb = OBJECT_GET_DATA(w, E_FILE_T_RESOLVE_KEY);
426 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)) ? RESOLV_TRANSPORT : RESOLV_NONE;
428 /* We've crossed the Rubicon; get rid of the file selection box. */
429 gtk_widget_hide(GTK_WIDGET (fs));
430 gtk_widget_destroy(GTK_WIDGET (fs));
432 switch (cf_read(&cfile)) {
436 /* Just because we got an error, that doesn't mean we were unable
437 to read any of the file; we handle what we could get from the
442 /* The user bailed out of re-reading the capture file; the
443 capture file has been closed - just free the capture file name
444 string and return (without changing the last containing
450 /* Save the name of the containing directory specified in the path name,
451 if any; we can write over cf_name, which is a good thing, given that
452 "get_dirname()" does write over its argument. */
453 s = get_dirname(cf_name);
454 set_last_open_dir(s);
455 gtk_widget_grab_focus(packet_list);
461 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
463 /* Note that we no longer have a "Open Capture File" dialog box. */
467 void file_close_confirmed_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
471 /* save file first */
472 file_save_as_cmd(after_save_close_file, NULL);
477 case(ESD_BTN_CANCEL):
480 g_assert_not_reached();
486 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
489 if((cfile.state != FILE_CLOSED) && !cfile.user_saved) {
490 /* user didn't saved his current file, ask him */
491 dialog = simple_dialog(ESD_TYPE_WARN | ESD_TYPE_MODAL,
492 ESD_BTN_YES | ESD_BTN_NO | ESD_BTN_CANCEL,
493 PRIMARY_TEXT_START "Save capture file before closing it?" PRIMARY_TEXT_END "\n\n"
494 "If you close without saving, your capture data will be discarded.");
496 simple_dialog_set_cb(dialog, file_close_confirmed_cb, NULL);
498 /* unchanged file, just close it */
504 file_save_cmd_cb(GtkWidget *w, gpointer data) {
505 /* If the file's already been saved, do nothing. */
506 if (cfile.user_saved)
509 /* Do a "Save As". */
510 file_save_as_cmd_cb(w, data);
513 /* XXX - can we make these not be static? */
514 static packet_range_t range;
515 static gboolean color_marked;
517 static GtkWidget *captured_bt;
518 static GtkWidget *displayed_bt;
519 static GtkWidget *select_all_rb;
520 static GtkWidget *select_all_c_lb;
521 static GtkWidget *select_all_d_lb;
522 static GtkWidget *select_curr_rb;
523 static GtkWidget *select_curr_c_lb;
524 static GtkWidget *select_curr_d_lb;
525 static GtkWidget *select_marked_only_rb;
526 static GtkWidget *select_marked_only_c_lb;
527 static GtkWidget *select_marked_only_d_lb;
528 static GtkWidget *select_marked_range_rb;
529 static GtkWidget *select_marked_range_c_lb;
530 static GtkWidget *select_marked_range_d_lb;
531 static GtkWidget *select_user_range_rb;
532 static GtkWidget *select_user_range_c_lb;
533 static GtkWidget *select_user_range_d_lb;
534 static GtkWidget *select_user_range_entry;
535 static GtkWidget *cfmark_cb;
536 static GtkWidget *ft_om;
539 can_save_with_wiretap(int ft)
541 /* To save a file with Wiretap, Wiretap has to handle that format,
542 and its code to handle that format must be able to write a file
543 with this file's encapsulation type. */
544 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
548 file_set_save_dynamics(void) {
549 gboolean filtered_active;
550 gchar label_text[100];
554 filtered_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displayed_bt));
556 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(filetype));
558 gtk_widget_set_sensitive(select_all_c_lb, !filtered_active);
559 g_snprintf(label_text, sizeof(label_text), "%u", cfile.count);
560 gtk_label_set_text(GTK_LABEL(select_all_c_lb), label_text);
561 gtk_widget_set_sensitive(select_all_d_lb, filtered_active);
562 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_cnt);
564 gtk_label_set_text(GTK_LABEL(select_all_d_lb), label_text);
566 selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
567 /* XXX: how to update the radio button label but keep the mnemonic? */
568 /* g_snprintf(label_text, sizeof(label_text), "_Selected packet #%u only", selected_num);
569 gtk_label_set_text(GTK_LABEL(GTK_BIN(select_curr_rb)->child), label_text);*/
570 gtk_widget_set_sensitive(select_curr_rb, selected_num);
571 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
572 gtk_label_set_text(GTK_LABEL(select_curr_c_lb), label_text);
573 gtk_widget_set_sensitive(select_curr_c_lb, selected_num && !filtered_active);
574 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
575 gtk_label_set_text(GTK_LABEL(select_curr_d_lb), label_text);
576 gtk_widget_set_sensitive(select_curr_d_lb, selected_num && filtered_active);
578 gtk_widget_set_sensitive(select_marked_only_rb, cfile.marked_count);
579 g_snprintf(label_text, sizeof(label_text), "%u", cfile.marked_count);
580 gtk_label_set_text(GTK_LABEL(select_marked_only_c_lb), label_text);
581 gtk_widget_set_sensitive(select_marked_only_c_lb, cfile.marked_count && !filtered_active);
582 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_marked_cnt);
583 gtk_label_set_text(GTK_LABEL(select_marked_only_d_lb), label_text);
584 gtk_widget_set_sensitive(select_marked_only_d_lb, range.displayed_marked_cnt && filtered_active);
586 gtk_widget_set_sensitive(select_marked_range_rb, range.mark_range_cnt);
587 g_snprintf(label_text, sizeof(label_text), "%u", range.mark_range_cnt);
588 gtk_label_set_text(GTK_LABEL(select_marked_range_c_lb), label_text);
589 gtk_widget_set_sensitive(select_marked_range_c_lb, range.mark_range_cnt && !filtered_active);
590 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_mark_range_cnt);
591 gtk_label_set_text(GTK_LABEL(select_marked_range_d_lb), label_text);
592 gtk_widget_set_sensitive(select_marked_range_d_lb, range.displayed_mark_range_cnt && filtered_active);
594 gtk_widget_set_sensitive(select_user_range_rb, TRUE);
595 g_snprintf(label_text, sizeof(label_text), "%u", range.user_range_cnt);
596 gtk_label_set_text(GTK_LABEL(select_user_range_c_lb), label_text);
597 gtk_widget_set_sensitive(select_user_range_c_lb, !filtered_active);
598 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_user_range_cnt);
599 gtk_label_set_text(GTK_LABEL(select_user_range_d_lb), label_text);
600 gtk_widget_set_sensitive(select_user_range_d_lb, filtered_active);
603 /* Generate a list of the file types we can save this file as.
605 "filetype" is the type it has now.
607 "encap" is the encapsulation for its packets (which could be
608 "unknown" or "per-packet").
610 "filtered" is TRUE if we're to save only the packets that passed
611 the display filter (in which case we have to save it using Wiretap)
612 and FALSE if we're to save the entire file (in which case, if we're
613 saving it in the type it has already, we can just copy it).
615 The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
618 set_file_type_list(GtkWidget *option_menu)
620 GtkWidget *ft_menu, *ft_menu_item;
623 guint item_to_select;
625 /* Default to the first supported file type, if the file's current
626 type isn't supported. */
629 ft_menu = gtk_menu_new();
631 /* Check all file types. */
633 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
634 if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
635 /* not all unfiltered packets or a different file type. We have to use Wiretap. */
636 if (!can_save_with_wiretap(ft))
637 continue; /* We can't. */
640 /* OK, we can write it out in this type. */
641 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
642 if (ft == filetype) {
643 /* Default to the same format as the file, if it's supported. */
644 item_to_select = index;
646 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
647 GINT_TO_POINTER(ft));
648 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
649 gtk_widget_show(ft_menu_item);
653 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
654 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
658 select_file_type_cb(GtkWidget *w _U_, gpointer data)
660 int new_filetype = GPOINTER_TO_INT(data);
662 if (filetype != new_filetype) {
663 /* We can select only the filtered or marked packets to be saved if we can
664 use Wiretap to save the file. */
665 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(new_filetype));
666 filetype = new_filetype;
667 file_set_save_marked_sensitive();
672 toggle_captured_cb(GtkWidget *widget, gpointer data _U_)
674 /* is the button now active? */
675 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
676 /* They changed the state of the "captured" button. */
677 range.process_filtered = FALSE;
678 /* XXX: the following line fails, I have no idea why */
679 /* set_file_type_list(ft_om);*/
681 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
682 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
684 file_set_save_dynamics();
689 toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
691 /* is the button now active? */
692 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
693 range.process_filtered = TRUE;
694 set_file_type_list(ft_om);
696 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), FALSE);
697 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), TRUE);
699 file_set_save_dynamics();
704 toggle_select_all(GtkWidget *widget, gpointer data _U_)
706 /* is the button now active? */
707 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
708 range.process = range_process_all;
709 set_file_type_list(ft_om);
710 file_set_save_dynamics();
715 toggle_select_selected(GtkWidget *widget, gpointer data _U_)
717 /* is the button now active? */
718 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
719 range.process = range_process_selected;
720 set_file_type_list(ft_om);
721 file_set_save_dynamics();
726 toggle_select_marked_only(GtkWidget *widget, gpointer data _U_)
728 /* is the button now active? */
729 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
730 range.process = range_process_marked;
731 set_file_type_list(ft_om);
732 file_set_save_dynamics();
737 toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
739 /* is the button now active? */
740 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
741 range.process = range_process_marked_range;
742 set_file_type_list(ft_om);
743 file_set_save_dynamics();
748 toggle_select_user_range(GtkWidget *widget, gpointer data _U_)
750 /* is the button now active? */
751 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
752 range.process = range_process_user_range;
753 set_file_type_list(ft_om);
754 file_set_save_dynamics();
757 /* Make the entry widget sensitive or insensitive */
758 gtk_widget_set_sensitive(select_user_range_entry, range.process == range_process_user_range);
760 /* When selecting user specified range, then focus on the entry */
761 if (range.process == range_process_user_range)
762 gtk_widget_grab_focus(select_user_range_entry);
767 range_entry(GtkWidget *entry)
769 const gchar *entry_text;
771 entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
772 packet_range_convert_str(&range, entry_text);
773 file_set_save_dynamics();
777 * Set the "Save only marked packets" toggle button as appropriate for
778 * the current output file type and count of marked packets.
780 * Called when the "Save As..." dialog box is created and when either
781 * the file type or the marked count changes.
784 file_set_save_marked_sensitive(void)
786 if (file_save_as_w == NULL) {
787 /* We don't currently have a "Save As..." dialog box up. */
791 /* We can request that only the marked packets be saved only if we
792 can use Wiretap to save the file and if there *are* marked packets. */
793 if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
794 gtk_widget_set_sensitive(select_marked_only_rb, TRUE);
795 gtk_widget_set_sensitive(select_marked_range_rb, TRUE);
798 /* Force the "Save only marked packets" toggle to "false", turn
799 off the flag it controls, and update the list of types we can
801 range.process = range_process_all;
802 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_only_rb), FALSE);
803 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_range_rb), FALSE);
804 set_file_type_list(ft_om);
805 gtk_widget_set_sensitive(select_marked_only_rb, FALSE);
806 gtk_widget_set_sensitive(select_marked_range_rb, FALSE);
810 action_after_save_e action_after_save_g;
811 gpointer action_after_save_data_g;
815 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
817 GtkWidget *ok_bt, *main_vb, *ft_hb, *ft_lb, *range_fr, *range_tb;
818 GtkTooltips *tooltips;
820 #if GTK_MAJOR_VERSION < 2
821 GtkAccelGroup *accel_group;
824 if (file_save_as_w != NULL) {
825 /* There's already an "Save Capture File As" dialog box; reactivate it. */
826 reactivate_window(file_save_as_w);
830 /* Default to saving all packets, in the file's current format. */
831 filetype = cfile.cd_t;
833 /* init the packet range */
834 packet_range_init(&range);
836 /* Enable tooltips */
837 tooltips = gtk_tooltips_new();
839 /* build the file selection */
840 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As");
841 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
843 /* as the dialog might already be gone, when using this values, we cannot
844 * set data to the dialog object, but keep global values */
845 action_after_save_g = action_after_save;
846 action_after_save_data_g = action_after_save_data;
848 #if GTK_MAJOR_VERSION < 2
849 accel_group = gtk_accel_group_new();
850 gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
853 /* If we've opened a file, start out by showing the files in the directory
854 in which that file resided. */
856 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), last_open_dir);
858 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
859 pointer to the file selection box widget */
860 ok_bt = GTK_FILE_SELECTION (file_save_as_w)->ok_button;
861 SIGNAL_CONNECT(ok_bt, "clicked", file_save_as_ok_cb, file_save_as_w);
863 /* Container for each row of widgets */
865 main_vb = gtk_vbox_new(FALSE, 5);
866 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
867 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
868 main_vb, FALSE, FALSE, 0);
869 gtk_widget_show(main_vb);
871 /*** Packet Range frame ***/
872 range_fr = gtk_frame_new("Packet Range");
873 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
874 gtk_widget_show(range_fr);
877 range_tb = gtk_table_new(7, 3, FALSE);
878 gtk_container_border_width(GTK_CONTAINER(range_tb), 5);
879 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
880 gtk_widget_show(range_tb);
882 /* captured button */
883 captured_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Captured", accel_group);
884 gtk_table_attach_defaults(GTK_TABLE(range_tb), captured_bt, 1, 2, 0, 1);
885 SIGNAL_CONNECT(captured_bt, "toggled", toggle_captured_cb, NULL);
886 gtk_tooltips_set_tip (tooltips,captured_bt,("Process all the below chosen packets"), NULL);
887 gtk_widget_show(captured_bt);
889 /* displayed button */
890 displayed_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Displayed", accel_group);
891 gtk_table_attach_defaults(GTK_TABLE(range_tb), displayed_bt, 2, 3, 0, 1);
892 SIGNAL_CONNECT(displayed_bt, "toggled", toggle_filtered_cb, NULL);
893 gtk_tooltips_set_tip (tooltips,displayed_bt,("Process only the below chosen packets, which also passes the current display filter"), NULL);
894 gtk_widget_show(displayed_bt);
897 /* Process all packets */
898 select_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "_All packets", accel_group);
899 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 1, 2);
900 gtk_tooltips_set_tip (tooltips,select_all_rb,("Process all packets"), NULL);
901 SIGNAL_CONNECT(select_all_rb, "toggled", toggle_select_all, NULL);
902 gtk_widget_show(select_all_rb);
904 select_all_c_lb = gtk_label_new("?");
905 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_c_lb, 1, 2, 1, 2);
906 gtk_widget_show(select_all_c_lb);
907 select_all_d_lb = gtk_label_new("?");
908 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_d_lb, 2, 3, 1, 2);
909 gtk_widget_show(select_all_d_lb);
912 /* Process currently selected */
913 select_curr_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Selected packet only", accel_group);
914 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_rb, 0, 1, 2, 3);
915 gtk_tooltips_set_tip (tooltips,select_curr_rb,("Process the currently selected packet only"), NULL);
916 SIGNAL_CONNECT(select_curr_rb, "toggled", toggle_select_selected, NULL);
917 gtk_widget_show(select_curr_rb);
919 select_curr_c_lb = gtk_label_new("?");
920 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_c_lb, 1, 2, 2, 3);
921 gtk_widget_show(select_curr_c_lb);
922 select_curr_d_lb = gtk_label_new("?");
923 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_d_lb, 2, 3, 2, 3);
924 gtk_widget_show(select_curr_d_lb);
927 /* Process marked packets */
928 select_marked_only_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Marked packets only", accel_group);
929 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_rb, 0, 1, 3, 4);
930 gtk_tooltips_set_tip (tooltips,select_marked_only_rb,("Process marked packets only"), NULL);
931 SIGNAL_CONNECT(select_marked_only_rb, "toggled", toggle_select_marked_only, NULL);
932 gtk_widget_show(select_marked_only_rb);
934 select_marked_only_c_lb = gtk_label_new("?");
935 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_c_lb, 1, 2, 3, 4);
936 gtk_widget_show(select_marked_only_c_lb);
937 select_marked_only_d_lb = gtk_label_new("?");
938 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_d_lb, 2, 3, 3, 4);
939 gtk_widget_show(select_marked_only_d_lb);
942 /* Process packet range between first and last packet */
943 select_marked_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "From first _to last marked packet", accel_group);
944 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_rb, 0, 1, 4, 5);
945 gtk_tooltips_set_tip (tooltips,select_marked_range_rb,("Process all packets between the first and last marker"), NULL);
946 SIGNAL_CONNECT(select_marked_range_rb, "toggled", toggle_select_marked_range, NULL);
947 gtk_widget_show(select_marked_range_rb);
949 select_marked_range_c_lb = gtk_label_new("?");
950 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_c_lb, 1, 2, 4, 5);
951 gtk_widget_show(select_marked_range_c_lb);
952 select_marked_range_d_lb = gtk_label_new("?");
953 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_d_lb, 2, 3, 4, 5);
954 gtk_widget_show(select_marked_range_d_lb);
957 /* Process a user specified provided packet range : -10,30,40-70,80- */
958 select_user_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "Specify a packet _range:", accel_group);
959 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_rb, 0, 1, 5, 6);
960 gtk_tooltips_set_tip (tooltips,select_user_range_rb,("Process a specified packet range"), NULL);
961 SIGNAL_CONNECT(select_user_range_rb, "toggled", toggle_select_user_range, NULL);
962 gtk_widget_show(select_user_range_rb);
964 select_user_range_c_lb = gtk_label_new("?");
965 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_c_lb, 1, 2, 5, 6);
966 gtk_widget_show(select_user_range_c_lb);
967 select_user_range_d_lb = gtk_label_new("?");
968 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_d_lb, 2, 3, 5, 6);
969 gtk_widget_show(select_user_range_d_lb);
973 select_user_range_entry = gtk_entry_new();
974 gtk_entry_set_max_length (GTK_ENTRY (select_user_range_entry), 254);
975 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_entry, 0, 1, 6, 7);
976 gtk_tooltips_set_tip (tooltips,select_user_range_entry,
977 ("Specify a range of packet numbers : \nExample : 1-10,18,25-100,332-"), NULL);
978 SIGNAL_CONNECT(select_user_range_entry,"changed", range_entry, select_user_range_entry);
979 gtk_widget_set_sensitive(select_user_range_entry, FALSE);
980 gtk_widget_show(select_user_range_entry);
982 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
983 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
984 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb), TRUE);
987 ft_hb = gtk_hbox_new(FALSE, 3);
988 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
989 gtk_widget_show(ft_hb);
991 ft_lb = gtk_label_new("File type:");
992 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
993 gtk_widget_show(ft_lb);
995 ft_om = gtk_option_menu_new();
997 /* Generate the list of file types we can save. */
998 set_file_type_list(ft_om);
999 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1000 gtk_widget_show(ft_om);
1003 * Set the sensitivity of the "Save only marked packets" toggle
1006 * This has to be done after we create the file type menu option,
1007 * as the routine that sets it also sets that menu.
1009 file_set_save_marked_sensitive();
1011 /* dynamic values in the range frame */
1012 file_set_save_dynamics();
1014 /* Connect the cancel_button to destroy the widget */
1015 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
1016 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1019 /* Catch the "key_press_event" signal in the window, so that we can catch
1020 the ESC key being pressed and act as if the "Cancel" button had
1022 dlg_set_cancel(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
1024 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
1026 gtk_widget_show(file_save_as_w);
1030 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1032 file_save_as_cmd(after_save_no_action, NULL);
1036 file_save_as_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
1041 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1043 /* Perhaps the user specified a directory instead of a file.
1044 Check whether they did. */
1045 if (test_for_directory(cf_name) == EISDIR) {
1046 /* It's a directory - set the file selection box to display that
1047 directory, and leave the selection box displayed. */
1048 set_last_open_dir(cf_name);
1050 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1054 /* don't show the dialog while saving */
1055 gtk_widget_hide(GTK_WIDGET (fs));
1057 /* Write out the packets (all, or only the ones from the current
1058 range) to the file with the specified name. */
1059 if (! cf_save(cf_name, &cfile, &range, filetype)) {
1060 /* The write failed; don't dismiss the open dialog box,
1061 just leave it around so that the user can, after they
1062 dismiss the alert box popped up for the error, try again. */
1064 gtk_widget_show(GTK_WIDGET (fs));
1068 /* The write succeeded; get rid of the file selection box. */
1069 /* cf_save might already closed our dialog! */
1071 gtk_widget_destroy(GTK_WIDGET (fs));
1073 /* Save the directory name for future file dialogs. */
1074 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1075 set_last_open_dir(dirname);
1078 /* we have finished saving, do we have pending things to do? */
1079 switch(action_after_save_g) {
1080 case(after_save_no_action):
1082 case(after_save_open_dialog):
1083 file_open_cmd(action_after_save_data_g);
1085 case(after_save_open_recent_file):
1086 menu_open_recent_file_cmd(action_after_save_data_g);
1088 case(after_save_open_dnd_file):
1089 dnd_open_file_cmd(action_after_save_data_g);
1092 case(after_save_capture_dialog):
1096 case(after_save_close_file):
1099 case(after_save_exit):
1103 g_assert_not_reached();
1106 action_after_save_g = after_save_no_action;
1110 file_save_as_destroy(void)
1113 gtk_widget_destroy(file_save_as_w);
1117 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1119 /* Note that we no longer have a "Save Capture File As" dialog box. */
1120 file_save_as_w = NULL;
1123 /* Reload a file using the current read and display filters */
1125 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1127 gboolean is_tempfile;
1129 /* If the file could be opened, "cf_open()" calls "cf_close()"
1130 to get rid of state for the old capture file before filling in state
1131 for the new capture file. "cf_close()" will remove the file if
1132 it's a temporary file; we don't want that to happen (for one thing,
1133 it'd prevent subsequent reopens from working). Remember whether it's
1134 a temporary file, mark it as not being a temporary file, and then
1135 reopen it as the type of file it was.
1137 Also, "cf_close()" will free "cfile.filename", so we must make
1138 a copy of it first. */
1139 filename = g_strdup(cfile.filename);
1140 is_tempfile = cfile.is_tempfile;
1141 cfile.is_tempfile = FALSE;
1142 if (cf_open(filename, is_tempfile, &cfile) == 0) {
1143 switch (cf_read(&cfile)) {
1147 /* Just because we got an error, that doesn't mean we were unable
1148 to read any of the file; we handle what we could get from the
1153 /* The user bailed out of re-reading the capture file; the
1154 capture file has been closed - just free the capture file name
1155 string and return (without changing the last containing
1161 /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
1162 Instead, the file was left open, so we should restore "cfile.is_tempfile"
1165 XXX - change the menu? Presumably "cf_open()" will do that;
1166 make sure it does! */
1167 cfile.is_tempfile = is_tempfile;
1169 /* "cf_open()" made a copy of the file name we handed it, so
1170 we should free up our copy. */
1174 /******************** Color Filters *********************************/
1176 * Keep a static pointer to the current "Color Export" window, if
1177 * any, so that if somebody tries to do "Export"
1178 * while there's already a "Color Export" window up, we just pop
1179 * up the existing one, rather than creating a new one.
1181 static GtkWidget *file_color_import_w;
1183 /* sets the file path to the global color filter file.
1184 WARNING: called by both the import and the export dialog.
1187 color_global_cb(GtkWidget *widget _U_, gpointer data)
1189 GtkWidget *fs_widget = data;
1193 /* decide what file to open (from dfilter code) */
1194 path = get_datafile_path("colorfilters");
1196 gtk_file_selection_set_filename (GTK_FILE_SELECTION(fs_widget), path);
1198 g_free((gchar *)path);
1201 /* Import color filters */
1203 file_color_import_cmd_cb(GtkWidget *w _U_, gpointer data)
1205 GtkWidget *main_vb, *cfglobal_but;
1206 #if GTK_MAJOR_VERSION < 2
1207 GtkAccelGroup *accel_group;
1209 /* No Apply button, and "OK" just sets our text widget, it doesn't
1210 activate it (i.e., it doesn't cause us to try to open the file). */
1212 if (file_color_import_w != NULL) {
1213 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1214 reactivate_window(file_color_import_w);
1218 file_color_import_w = gtk_file_selection_new ("Ethereal: Import Color Filters");
1219 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1221 #if GTK_MAJOR_VERSION < 2
1222 /* Accelerator group for the accelerators (or, as they're called in
1223 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
1224 Ctrl+<key> is an accelerator). */
1225 accel_group = gtk_accel_group_new();
1226 gtk_window_add_accel_group(GTK_WINDOW(file_color_import_w), accel_group);
1229 /* If we've opened a file, start out by showing the files in the directory
1230 in which that file resided. */
1232 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_import_w), last_open_dir);
1234 /* Container for each row of widgets */
1235 main_vb = gtk_vbox_new(FALSE, 3);
1236 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1237 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_import_w)->action_area),
1238 main_vb, FALSE, FALSE, 0);
1239 gtk_widget_show(main_vb);
1242 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1243 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1244 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1245 gtk_widget_show(cfglobal_but);
1247 /* Connect the ok_button to file_open_ok_cb function and pass along a
1248 pointer to the file selection box widget */
1249 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1250 file_color_import_ok_cb, file_color_import_w);
1252 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_color_import_w)->ok_button,
1255 /* Connect the cancel_button to destroy the widget */
1256 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_import_w)->cancel_button,
1257 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1258 file_color_import_w);
1260 /* Catch the "key_press_event" signal in the window, so that we can catch
1261 the ESC key being pressed and act as if the "Cancel" button had
1263 dlg_set_cancel(file_color_import_w, GTK_FILE_SELECTION(file_color_import_w)->cancel_button);
1265 gtk_widget_show(file_color_import_w);
1269 file_color_import_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
1273 argument = OBJECT_GET_DATA(w, ARGUMENT_CL); /* to be passed back into read_other_filters */
1275 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
1276 /* Perhaps the user specified a directory instead of a file.
1277 Check whether they did. */
1278 if (test_for_directory(cf_name) == EISDIR) {
1279 /* It's a directory - set the file selection box to display that
1280 directory, don't try to open the directory as a capture file. */
1281 set_last_open_dir(cf_name);
1283 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1287 /* Try to open the capture file. */
1289 if (!read_other_filters(cf_name, argument)) {
1290 /* We couldn't open it; don't dismiss the open dialog box,
1291 just leave it around so that the user can, after they
1292 dismiss the alert box popped up for the open error,
1298 /* We've crossed the Rubicon; get rid of the file selection box. */
1299 gtk_widget_hide(GTK_WIDGET (fs));
1300 gtk_widget_destroy(GTK_WIDGET (fs));
1302 /* Save the name of the containing directory specified in the path name,
1303 if any; we can write over cf_name, which is a good thing, given that
1304 "get_dirname()" does write over its argument. */
1305 s = get_dirname(cf_name);
1306 set_last_open_dir(s);
1307 gtk_widget_grab_focus(packet_list);
1313 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1315 /* Note that we no longer have a "Open Capture File" dialog box. */
1316 file_color_import_w = NULL;
1319 static GtkWidget *file_color_export_w;
1321 * Set the "Export only marked filters" toggle button as appropriate for
1322 * the current output file type and count of marked filters.
1324 * Called when the "Export" dialog box is created and when the marked
1328 color_set_export_marked_sensitive(GtkWidget * cfmark_cb)
1330 if (file_color_export_w == NULL) {
1331 /* We don't currently have an "Export" dialog box up. */
1335 /* We can request that only the marked filters be saved only if
1336 there *are* marked filters. */
1337 if (color_marked_count() != 0)
1338 gtk_widget_set_sensitive(cfmark_cb, TRUE);
1340 /* Force the "Export only marked filters" toggle to "false", turn
1341 off the flag it controls. */
1342 color_marked = FALSE;
1343 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1344 gtk_widget_set_sensitive(cfmark_cb, FALSE);
1349 color_toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
1351 color_marked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1355 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1357 GtkWidget *ok_bt, *main_vb, *cfglobal_but;
1359 if (file_color_export_w != NULL) {
1360 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1361 reactivate_window(file_color_export_w);
1365 /* Default to saving all packets, in the file's current format. */
1366 color_marked = FALSE;
1367 filetype = cfile.cd_t;
1369 file_color_export_w = gtk_file_selection_new ("Ethereal: Export Color Filters");
1370 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1372 /* If we've opened a file, start out by showing the files in the directory
1373 in which that file resided. */
1375 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), last_open_dir);
1377 /* Connect the ok_button to file_export_ok_cb function and pass along a
1378 pointer to the file selection box widget */
1379 ok_bt = GTK_FILE_SELECTION (file_color_export_w)->ok_button;
1380 SIGNAL_CONNECT(ok_bt, "clicked", file_color_export_ok_cb, file_color_export_w);
1382 /* Container for each row of widgets */
1383 main_vb = gtk_vbox_new(FALSE, 3);
1384 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1385 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_export_w)->action_area),
1386 main_vb, FALSE, FALSE, 0);
1387 gtk_widget_show(main_vb);
1389 cfmark_cb = gtk_check_button_new_with_label("Export only marked filters");
1390 gtk_container_add(GTK_CONTAINER(main_vb), cfmark_cb);
1391 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1392 SIGNAL_CONNECT(cfmark_cb, "toggled", color_toggle_marked_cb, NULL);
1393 gtk_widget_show(cfmark_cb);
1394 color_set_export_marked_sensitive(cfmark_cb);
1396 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1397 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1398 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1399 gtk_widget_show(cfglobal_but);
1401 /* Connect the cancel_button to destroy the widget */
1402 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_export_w)->cancel_button,
1403 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1404 file_color_export_w);
1406 /* Catch the "key_press_event" signal in the window, so that we can catch
1407 the ESC key being pressed and act as if the "Cancel" button had
1409 dlg_set_cancel(file_color_export_w, GTK_FILE_SELECTION(file_color_export_w)->cancel_button);
1411 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1413 gtk_widget_show(file_color_export_w);
1417 file_color_export_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
1421 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1423 /* Perhaps the user specified a directory instead of a file.
1424 Check whether they did. */
1425 if (test_for_directory(cf_name) == EISDIR) {
1426 /* It's a directory - set the file selection box to display that
1427 directory, and leave the selection box displayed. */
1428 set_last_open_dir(cf_name);
1430 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1434 /* Write out the filters (all, or only the ones that are currently
1435 displayed or marked) to the file with the specified name. */
1437 if (!write_other_filters(cf_name, color_marked))
1439 /* The write failed; don't dismiss the open dialog box,
1440 just leave it around so that the user can, after they
1441 dismiss the alert box popped up for the error, try again. */
1447 /* The write succeeded; get rid of the file selection box. */
1448 gtk_widget_hide(GTK_WIDGET (fs));
1449 gtk_widget_destroy(GTK_WIDGET (fs));
1451 /* Save the directory name for future file dialogs. */
1452 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1453 set_last_open_dir(dirname);
1458 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1460 file_color_export_w = NULL;