2 * Dialog boxes for handling files
4 * $Id: file_dlg.c,v 1.83 2004/01/20 02:21:17 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 static void file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs);
53 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
54 static void select_file_type_cb(GtkWidget *w, gpointer data);
55 static void file_save_as_ok_cb(GtkWidget *w, GtkFileSelection *fs);
56 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
57 static void file_color_import_ok_cb(GtkWidget *w, GtkFileSelection *fs);
58 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
59 static void file_color_export_ok_cb(GtkWidget *w, GtkFileSelection *fs);
60 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
61 static void file_select_ok_cb(GtkWidget *w, gpointer data);
62 static void file_select_cancel_cb(GtkWidget *w, gpointer data);
63 static void file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te);
64 static void toggle_captured_cb(GtkWidget *widget, gpointer data _U_);
66 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
67 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
68 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
70 #define ARGUMENT_CL "argument_cl"
73 * Keep a static pointer to the current "Save Capture File As" window, if
74 * any, so that if somebody tries to do "File:Save" or "File:Save As"
75 * while there's already a "Save Capture File As" window up, we just pop
76 * up the existing one, rather than creating a new one.
78 static GtkWidget *file_save_as_w;
81 * A generic select_file_cb routine that is intended to be connected to
82 * a Browse button on other dialog boxes. This allows the user to browse
83 * for a file and select it. We fill in the text_entry that is asssociated
84 * with the button that invoked us.
86 * We display the window label specified in our args.
89 select_file_cb(GtkWidget *file_bt, const char *label)
91 GtkWidget *caller = gtk_widget_get_toplevel(file_bt);
92 GtkWidget *fs, *file_te;
94 /* Has a file selection dialog box already been opened for that top-level
96 fs = OBJECT_GET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY);
97 file_te = OBJECT_GET_DATA(file_bt, E_FILE_TE_PTR_KEY);
99 /* Yes. Just re-activate that dialog box. */
100 reactivate_window(fs);
104 fs = file_selection_new (label);
106 /* If we've opened a file, start out by showing the files in the directory
107 in which that file resided. */
109 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
111 OBJECT_SET_DATA(fs, PRINT_FILE_TE_KEY, file_te);
113 /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
114 OBJECT_SET_DATA(fs, E_FS_CALLER_PTR_KEY, caller);
116 /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
117 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, fs);
119 /* Call a handler when the file selection box is destroyed, so we can inform
120 our caller, if any, that it's been destroyed. */
121 SIGNAL_CONNECT(fs, "destroy", GTK_SIGNAL_FUNC(file_select_destroy_cb),
124 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->ok_button, "clicked",
125 file_select_ok_cb, fs);
127 /* Connect the cancel_button to destroy the widget */
128 SIGNAL_CONNECT(GTK_FILE_SELECTION(fs)->cancel_button, "clicked",
129 file_select_cancel_cb, fs);
131 /* Catch the "key_press_event" signal in the window, so that we can catch
132 the ESC key being pressed and act as if the "Cancel" button had
134 dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
140 file_select_ok_cb(GtkWidget *w _U_, gpointer data)
144 f_name = g_strdup(gtk_file_selection_get_filename(
145 GTK_FILE_SELECTION (data)));
147 /* Perhaps the user specified a directory instead of a file.
148 Check whether they did. */
149 if (test_for_directory(f_name) == EISDIR) {
150 /* It's a directory - set the file selection box to display it. */
151 set_last_open_dir(f_name);
153 gtk_file_selection_set_filename(GTK_FILE_SELECTION(data),
158 gtk_entry_set_text(GTK_ENTRY(OBJECT_GET_DATA(data, PRINT_FILE_TE_KEY)),
160 gtk_widget_destroy(GTK_WIDGET(data));
166 file_select_cancel_cb(GtkWidget *w _U_, gpointer data)
168 gtk_widget_destroy(GTK_WIDGET(data));
172 file_select_destroy_cb(GtkWidget *win, GtkWidget* file_te)
176 /* Get the widget that requested that we be popped up.
177 (It should arrange to destroy us if it's destroyed, so
178 that we don't get a pointer to a non-existent window here.) */
179 caller = OBJECT_GET_DATA(win, E_FS_CALLER_PTR_KEY);
181 /* Tell it we no longer exist. */
182 OBJECT_SET_DATA(caller, E_FILE_SEL_DIALOG_PTR_KEY, NULL);
184 /* Now nuke this window. */
185 gtk_grab_remove(GTK_WIDGET(win));
186 gtk_widget_destroy(GTK_WIDGET(win));
188 /* Give the focus to the file text entry widget so the user can just press
189 Return to print to the file. */
190 gtk_widget_grab_focus(file_te);
194 * Keep a static pointer to the current "Open Capture File" window, if
195 * any, so that if somebody tries to do "File:Open" while there's already
196 * an "Open Capture File" window up, we just pop up the existing one,
197 * rather than creating a new one.
199 static GtkWidget *file_open_w;
203 file_open_cmd_cb(GtkWidget *w, gpointer data _U_)
205 GtkWidget *main_vb, *filter_hbox, *filter_bt, *filter_te,
206 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
207 #if GTK_MAJOR_VERSION < 2
208 GtkAccelGroup *accel_group;
210 /* No Apply button, and "OK" just sets our text widget, it doesn't
211 activate it (i.e., it doesn't cause us to try to open the file). */
212 static construct_args_t args = {
213 "Ethereal: Read Filter",
218 if (file_open_w != NULL) {
219 /* There's already an "Open Capture File" dialog box; reactivate it. */
220 reactivate_window(file_open_w);
224 file_open_w = file_selection_new ("Ethereal: Open Capture File");
225 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
227 #if GTK_MAJOR_VERSION < 2
228 /* Accelerator group for the accelerators (or, as they're called in
229 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
230 Ctrl+<key> is an accelerator). */
231 accel_group = gtk_accel_group_new();
232 gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
235 switch (prefs.gui_fileopen_style) {
237 case FO_STYLE_LAST_OPENED:
238 /* The user has specified that we should start out in the last directory
239 we looked in. If we've already opened a file, use its containing
240 directory, if we could determine it, as the directory, otherwise
241 use the "last opened" directory saved in the preferences file if
244 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
248 if (prefs.gui_fileopen_remembered_dir != NULL) {
249 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
250 prefs.gui_fileopen_remembered_dir);
255 case FO_STYLE_SPECIFIED:
256 /* The user has specified that we should always start out in a
257 specified directory; if they've specified that directory,
258 start out by showing the files in that dir. */
259 if (prefs.gui_fileopen_dir[0] != '\0') {
260 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_open_w),
261 prefs.gui_fileopen_dir);
266 /* Container for each row of widgets */
267 main_vb = gtk_vbox_new(FALSE, 3);
268 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
269 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_open_w)->action_area),
270 main_vb, FALSE, FALSE, 0);
271 gtk_widget_show(main_vb);
273 filter_hbox = gtk_hbox_new(FALSE, 1);
274 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
275 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
276 gtk_widget_show(filter_hbox);
278 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
279 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
280 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
281 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
282 gtk_widget_show(filter_bt);
284 filter_te = gtk_entry_new();
285 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
286 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
287 gtk_widget_show(filter_te);
289 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
290 E_RFILTER_TE_KEY, filter_te);
292 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
293 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
294 g_resolv_flags & RESOLV_MAC);
295 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
296 gtk_widget_show(m_resolv_cb);
297 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
298 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
300 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
301 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
302 g_resolv_flags & RESOLV_NETWORK);
303 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
304 gtk_widget_show(n_resolv_cb);
305 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
306 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
308 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
309 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
310 g_resolv_flags & RESOLV_TRANSPORT);
311 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
312 gtk_widget_show(t_resolv_cb);
313 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
314 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
316 /* Connect the ok_button to file_open_ok_cb function and pass along a
317 pointer to the file selection box widget */
318 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
319 file_open_ok_cb, file_open_w);
321 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
322 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
324 /* Connect the cancel_button to destroy the widget */
325 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_open_w)->cancel_button,
326 "clicked", (GtkSignalFunc)gtk_widget_destroy,
329 /* Catch the "key_press_event" signal in the window, so that we can catch
330 the ESC key being pressed and act as if the "Cancel" button had
332 dlg_set_cancel(file_open_w, GTK_FILE_SELECTION(file_open_w)->cancel_button);
334 gtk_widget_show(file_open_w);
338 file_open_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
339 gchar *cf_name, *rfilter, *s;
340 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
341 dfilter_t *rfcode = NULL;
344 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
345 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
346 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
347 if (!dfilter_compile(rfilter, &rfcode)) {
349 simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
353 /* Perhaps the user specified a directory instead of a file.
354 Check whether they did. */
355 if (test_for_directory(cf_name) == EISDIR) {
356 /* It's a directory - set the file selection box to display that
357 directory, don't try to open the directory as a capture file. */
358 set_last_open_dir(cf_name);
360 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
364 /* Try to open the capture file. */
365 if ((err = cf_open(cf_name, FALSE, &cfile)) != 0) {
366 /* We couldn't open it; don't dismiss the open dialog box,
367 just leave it around so that the user can, after they
368 dismiss the alert box popped up for the open error,
371 dfilter_free(rfcode);
376 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
377 it closed the previous capture file, and thus destroyed any
378 previous read filter attached to "cf"). */
379 cfile.rfcode = rfcode;
381 /* Set the global resolving variable */
382 g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
383 m_resolv_cb = OBJECT_GET_DATA(w, E_FILE_M_RESOLVE_KEY);
384 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)) ? RESOLV_MAC : RESOLV_NONE;
385 n_resolv_cb = OBJECT_GET_DATA(w, E_FILE_N_RESOLVE_KEY);
386 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)) ? RESOLV_NETWORK : RESOLV_NONE;
387 t_resolv_cb = OBJECT_GET_DATA(w, E_FILE_T_RESOLVE_KEY);
388 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)) ? RESOLV_TRANSPORT : RESOLV_NONE;
390 /* We've crossed the Rubicon; get rid of the file selection box. */
391 gtk_widget_hide(GTK_WIDGET (fs));
392 gtk_widget_destroy(GTK_WIDGET (fs));
394 switch (cf_read(&cfile, &err)) {
398 /* Just because we got an error, that doesn't mean we were unable
399 to read any of the file; we handle what we could get from the
404 /* The user bailed out of re-reading the capture file; the
405 capture file has been closed - just free the capture file name
406 string and return (without changing the last containing
412 /* Save the name of the containing directory specified in the path name,
413 if any; we can write over cf_name, which is a good thing, given that
414 "get_dirname()" does write over its argument. */
415 s = get_dirname(cf_name);
416 set_last_open_dir(s);
417 gtk_widget_grab_focus(packet_list);
423 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
425 /* Note that we no longer have a "Open Capture File" dialog box. */
431 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
436 file_save_cmd_cb(GtkWidget *w, gpointer data) {
437 /* If the file's already been saved, do nothing. */
438 if (cfile.user_saved)
441 /* Do a "Save As". */
442 file_save_as_cmd_cb(w, data);
445 /* XXX - can we make these not be static? */
446 static packet_range_t range;
447 static gboolean color_marked;
449 static GtkWidget *captured_bt;
450 static GtkWidget *displayed_bt;
451 static GtkWidget *select_all_rb;
452 static GtkWidget *select_all_c_lb;
453 static GtkWidget *select_all_d_lb;
454 static GtkWidget *select_curr_rb;
455 static GtkWidget *select_curr_c_lb;
456 static GtkWidget *select_curr_d_lb;
457 static GtkWidget *select_marked_only_rb;
458 static GtkWidget *select_marked_only_c_lb;
459 static GtkWidget *select_marked_only_d_lb;
460 static GtkWidget *select_marked_range_rb;
461 static GtkWidget *select_marked_range_c_lb;
462 static GtkWidget *select_marked_range_d_lb;
463 static GtkWidget *select_user_range_rb;
464 static GtkWidget *select_user_range_c_lb;
465 static GtkWidget *select_user_range_d_lb;
466 static GtkWidget *select_user_range_entry;
467 static GtkWidget *cfmark_cb;
468 static GtkWidget *ft_om;
471 can_save_with_wiretap(int ft)
473 /* To save a file with Wiretap, Wiretap has to handle that format,
474 and its code to handle that format must be able to write a file
475 with this file's encapsulation type. */
476 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
480 file_set_save_dynamics(void) {
481 gboolean filtered_active;
482 gchar label_text[100];
486 filtered_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displayed_bt));
488 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(filetype));
490 gtk_widget_set_sensitive(select_all_c_lb, !filtered_active);
491 g_snprintf(label_text, sizeof(label_text), "%u", cfile.count);
492 gtk_label_set_text(GTK_LABEL(select_all_c_lb), label_text);
493 gtk_widget_set_sensitive(select_all_d_lb, filtered_active);
494 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_cnt);
496 gtk_label_set_text(GTK_LABEL(select_all_d_lb), label_text);
498 selected_num = (cfile.current_frame) ? cfile.current_frame->num : 0;
499 /* XXX: how to update the radio button label but keep the mnemonic? */
500 /* g_snprintf(label_text, sizeof(label_text), "_Selected packet #%u only", selected_num);
501 gtk_label_set_text(GTK_LABEL(GTK_BIN(select_curr_rb)->child), label_text);*/
502 gtk_widget_set_sensitive(select_curr_rb, selected_num);
503 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
504 gtk_label_set_text(GTK_LABEL(select_curr_c_lb), label_text);
505 gtk_widget_set_sensitive(select_curr_c_lb, selected_num && !filtered_active);
506 g_snprintf(label_text, sizeof(label_text), "%u", selected_num ? 1 : 0);
507 gtk_label_set_text(GTK_LABEL(select_curr_d_lb), label_text);
508 gtk_widget_set_sensitive(select_curr_d_lb, selected_num && filtered_active);
510 gtk_widget_set_sensitive(select_marked_only_rb, cfile.marked_count);
511 g_snprintf(label_text, sizeof(label_text), "%u", cfile.marked_count);
512 gtk_label_set_text(GTK_LABEL(select_marked_only_c_lb), label_text);
513 gtk_widget_set_sensitive(select_marked_only_c_lb, cfile.marked_count && !filtered_active);
514 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_marked_cnt);
515 gtk_label_set_text(GTK_LABEL(select_marked_only_d_lb), label_text);
516 gtk_widget_set_sensitive(select_marked_only_d_lb, range.displayed_marked_cnt && filtered_active);
518 gtk_widget_set_sensitive(select_marked_range_rb, range.mark_range_cnt);
519 g_snprintf(label_text, sizeof(label_text), "%u", range.mark_range_cnt);
520 gtk_label_set_text(GTK_LABEL(select_marked_range_c_lb), label_text);
521 gtk_widget_set_sensitive(select_marked_range_c_lb, range.mark_range_cnt && !filtered_active);
522 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_mark_range_cnt);
523 gtk_label_set_text(GTK_LABEL(select_marked_range_d_lb), label_text);
524 gtk_widget_set_sensitive(select_marked_range_d_lb, range.displayed_mark_range_cnt && filtered_active);
526 gtk_widget_set_sensitive(select_user_range_rb, TRUE);
527 g_snprintf(label_text, sizeof(label_text), "%u", range.user_range_cnt);
528 gtk_label_set_text(GTK_LABEL(select_user_range_c_lb), label_text);
529 gtk_widget_set_sensitive(select_user_range_c_lb, !filtered_active);
530 g_snprintf(label_text, sizeof(label_text), "%u", range.displayed_user_range_cnt);
531 gtk_label_set_text(GTK_LABEL(select_user_range_d_lb), label_text);
532 gtk_widget_set_sensitive(select_user_range_d_lb, filtered_active);
535 /* Generate a list of the file types we can save this file as.
537 "filetype" is the type it has now.
539 "encap" is the encapsulation for its packets (which could be
540 "unknown" or "per-packet").
542 "filtered" is TRUE if we're to save only the packets that passed
543 the display filter (in which case we have to save it using Wiretap)
544 and FALSE if we're to save the entire file (in which case, if we're
545 saving it in the type it has already, we can just copy it).
547 The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
550 set_file_type_list(GtkWidget *option_menu)
552 GtkWidget *ft_menu, *ft_menu_item;
555 guint item_to_select;
557 /* Default to the first supported file type, if the file's current
558 type isn't supported. */
561 ft_menu = gtk_menu_new();
563 /* Check all file types. */
565 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
566 if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
567 /* not all unfiltered packets or a different file type. We have to use Wiretap. */
568 if (!can_save_with_wiretap(ft))
569 continue; /* We can't. */
572 /* OK, we can write it out in this type. */
573 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
574 if (ft == filetype) {
575 /* Default to the same format as the file, if it's supported. */
576 item_to_select = index;
578 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
579 GINT_TO_POINTER(ft));
580 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
581 gtk_widget_show(ft_menu_item);
585 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
586 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
590 select_file_type_cb(GtkWidget *w _U_, gpointer data)
592 int new_filetype = GPOINTER_TO_INT(data);
594 if (filetype != new_filetype) {
595 /* We can select only the filtered or marked packets to be saved if we can
596 use Wiretap to save the file. */
597 gtk_widget_set_sensitive(displayed_bt, can_save_with_wiretap(new_filetype));
598 filetype = new_filetype;
599 file_set_save_marked_sensitive();
604 toggle_captured_cb(GtkWidget *widget, gpointer data _U_)
606 /* is the button now active? */
607 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
608 /* They changed the state of the "captured" button. */
609 range.process_filtered = FALSE;
610 /* XXX: the following line fails, I have no idea why */
611 /* set_file_type_list(ft_om);*/
613 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
614 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
616 file_set_save_dynamics();
621 toggle_filtered_cb(GtkWidget *widget, gpointer data _U_)
623 /* is the button now active? */
624 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
625 range.process_filtered = TRUE;
626 set_file_type_list(ft_om);
628 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), FALSE);
629 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), TRUE);
631 file_set_save_dynamics();
636 toggle_select_all(GtkWidget *widget, gpointer data _U_)
638 /* is the button now active? */
639 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
640 range.process = range_process_all;
641 set_file_type_list(ft_om);
642 file_set_save_dynamics();
647 toggle_select_selected(GtkWidget *widget, gpointer data _U_)
649 /* is the button now active? */
650 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
651 range.process = range_process_selected;
652 set_file_type_list(ft_om);
653 file_set_save_dynamics();
658 toggle_select_marked_only(GtkWidget *widget, gpointer data _U_)
660 /* is the button now active? */
661 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
662 range.process = range_process_marked;
663 set_file_type_list(ft_om);
664 file_set_save_dynamics();
669 toggle_select_marked_range(GtkWidget *widget, gpointer data _U_)
671 /* is the button now active? */
672 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
673 range.process = range_process_marked_range;
674 set_file_type_list(ft_om);
675 file_set_save_dynamics();
680 toggle_select_user_range(GtkWidget *widget, gpointer data _U_)
682 /* is the button now active? */
683 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget))) {
684 range.process = range_process_user_range;
685 set_file_type_list(ft_om);
686 file_set_save_dynamics();
689 /* Make the entry widget sensitive or insensitive */
690 gtk_widget_set_sensitive(select_user_range_entry, range.process == range_process_user_range);
692 /* When selecting user specified range, then focus on the entry */
693 if (range.process == range_process_user_range)
694 gtk_widget_grab_focus(select_user_range_entry);
699 range_entry(GtkWidget *entry)
701 const gchar *entry_text;
703 entry_text = gtk_entry_get_text (GTK_ENTRY (entry));
704 packet_range_convert_str(&range, entry_text);
705 file_set_save_dynamics();
709 * Set the "Save only marked packets" toggle button as appropriate for
710 * the current output file type and count of marked packets.
712 * Called when the "Save As..." dialog box is created and when either
713 * the file type or the marked count changes.
716 file_set_save_marked_sensitive(void)
718 if (file_save_as_w == NULL) {
719 /* We don't currently have a "Save As..." dialog box up. */
723 /* We can request that only the marked packets be saved only if we
724 can use Wiretap to save the file and if there *are* marked packets. */
725 if (can_save_with_wiretap(filetype) && cfile.marked_count != 0) {
726 gtk_widget_set_sensitive(select_marked_only_rb, TRUE);
727 gtk_widget_set_sensitive(select_marked_range_rb, TRUE);
730 /* Force the "Save only marked packets" toggle to "false", turn
731 off the flag it controls, and update the list of types we can
733 range.process = range_process_all;
734 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_only_rb), FALSE);
735 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_marked_range_rb), FALSE);
736 set_file_type_list(ft_om);
737 gtk_widget_set_sensitive(select_marked_only_rb, FALSE);
738 gtk_widget_set_sensitive(select_marked_range_rb, FALSE);
743 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
745 GtkWidget *ok_bt, *main_vb, *ft_hb, *ft_lb, *range_fr, *range_tb;
746 GtkTooltips *tooltips;
748 #if GTK_MAJOR_VERSION < 2
749 GtkAccelGroup *accel_group;
752 if (file_save_as_w != NULL) {
753 /* There's already an "Save Capture File As" dialog box; reactivate it. */
754 reactivate_window(file_save_as_w);
758 /* Default to saving all packets, in the file's current format. */
759 filetype = cfile.cd_t;
761 /* init the packet range */
762 packet_range_init(&range);
764 /* Enable tooltips */
765 tooltips = gtk_tooltips_new();
767 /* build the file selection */
768 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As");
769 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
771 #if GTK_MAJOR_VERSION < 2
772 accel_group = gtk_accel_group_new();
773 gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
776 /* If we've opened a file, start out by showing the files in the directory
777 in which that file resided. */
779 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), last_open_dir);
781 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
782 pointer to the file selection box widget */
783 ok_bt = GTK_FILE_SELECTION (file_save_as_w)->ok_button;
784 SIGNAL_CONNECT(ok_bt, "clicked", file_save_as_ok_cb, file_save_as_w);
786 /* Container for each row of widgets */
788 main_vb = gtk_vbox_new(FALSE, 5);
789 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
790 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_save_as_w)->action_area),
791 main_vb, FALSE, FALSE, 0);
792 gtk_widget_show(main_vb);
794 /*** Packet Range frame ***/
795 range_fr = gtk_frame_new("Packet Range");
796 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
797 gtk_widget_show(range_fr);
800 range_tb = gtk_table_new(7, 3, FALSE);
801 gtk_container_border_width(GTK_CONTAINER(range_tb), 5);
802 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
803 gtk_widget_show(range_tb);
805 /* captured button */
806 captured_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Captured", accel_group);
807 gtk_table_attach_defaults(GTK_TABLE(range_tb), captured_bt, 1, 2, 0, 1);
808 SIGNAL_CONNECT(captured_bt, "toggled", toggle_captured_cb, NULL);
809 gtk_tooltips_set_tip (tooltips,captured_bt,("Process all the below chosen packets"), NULL);
810 gtk_widget_show(captured_bt);
812 /* displayed button */
813 displayed_bt = TOGGLE_BUTTON_NEW_WITH_MNEMONIC("_Displayed", accel_group);
814 gtk_table_attach_defaults(GTK_TABLE(range_tb), displayed_bt, 2, 3, 0, 1);
815 SIGNAL_CONNECT(displayed_bt, "toggled", toggle_filtered_cb, NULL);
816 gtk_tooltips_set_tip (tooltips,displayed_bt,("Process only the below chosen packets, which also passes the current display filter"), NULL);
817 gtk_widget_show(displayed_bt);
820 /* Process all packets */
821 select_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "_All packets", accel_group);
822 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_rb, 0, 1, 1, 2);
823 gtk_tooltips_set_tip (tooltips,select_all_rb,("Process all packets"), NULL);
824 SIGNAL_CONNECT(select_all_rb, "toggled", toggle_select_all, NULL);
825 gtk_widget_show(select_all_rb);
827 select_all_c_lb = gtk_label_new("?");
828 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_c_lb, 1, 2, 1, 2);
829 gtk_widget_show(select_all_c_lb);
830 select_all_d_lb = gtk_label_new("?");
831 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_all_d_lb, 2, 3, 1, 2);
832 gtk_widget_show(select_all_d_lb);
835 /* Process currently selected */
836 select_curr_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Selected packet only", accel_group);
837 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_rb, 0, 1, 2, 3);
838 gtk_tooltips_set_tip (tooltips,select_curr_rb,("Process the currently selected packet only"), NULL);
839 SIGNAL_CONNECT(select_curr_rb, "toggled", toggle_select_selected, NULL);
840 gtk_widget_show(select_curr_rb);
842 select_curr_c_lb = gtk_label_new("?");
843 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_c_lb, 1, 2, 2, 3);
844 gtk_widget_show(select_curr_c_lb);
845 select_curr_d_lb = gtk_label_new("?");
846 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_curr_d_lb, 2, 3, 2, 3);
847 gtk_widget_show(select_curr_d_lb);
850 /* Process marked packets */
851 select_marked_only_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "_Marked packets only", accel_group);
852 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_rb, 0, 1, 3, 4);
853 gtk_tooltips_set_tip (tooltips,select_marked_only_rb,("Process marked packets only"), NULL);
854 SIGNAL_CONNECT(select_marked_only_rb, "toggled", toggle_select_marked_only, NULL);
855 gtk_widget_show(select_marked_only_rb);
857 select_marked_only_c_lb = gtk_label_new("?");
858 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_c_lb, 1, 2, 3, 4);
859 gtk_widget_show(select_marked_only_c_lb);
860 select_marked_only_d_lb = gtk_label_new("?");
861 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_only_d_lb, 2, 3, 3, 4);
862 gtk_widget_show(select_marked_only_d_lb);
865 /* Process packet range between first and last packet */
866 select_marked_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "From first _to last marked packet", accel_group);
867 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_rb, 0, 1, 4, 5);
868 gtk_tooltips_set_tip (tooltips,select_marked_range_rb,("Process all packets between the first and last marker"), NULL);
869 SIGNAL_CONNECT(select_marked_range_rb, "toggled", toggle_select_marked_range, NULL);
870 gtk_widget_show(select_marked_range_rb);
872 select_marked_range_c_lb = gtk_label_new("?");
873 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_c_lb, 1, 2, 4, 5);
874 gtk_widget_show(select_marked_range_c_lb);
875 select_marked_range_d_lb = gtk_label_new("?");
876 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_marked_range_d_lb, 2, 3, 4, 5);
877 gtk_widget_show(select_marked_range_d_lb);
880 /* Process a user specified provided packet range : -10,30,40-70,80- */
881 select_user_range_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(select_all_rb, "Specify a packet _range:", accel_group);
882 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_rb, 0, 1, 5, 6);
883 gtk_tooltips_set_tip (tooltips,select_user_range_rb,("Process a specified packet range"), NULL);
884 SIGNAL_CONNECT(select_user_range_rb, "toggled", toggle_select_user_range, NULL);
885 gtk_widget_show(select_user_range_rb);
887 select_user_range_c_lb = gtk_label_new("?");
888 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_c_lb, 1, 2, 5, 6);
889 gtk_widget_show(select_user_range_c_lb);
890 select_user_range_d_lb = gtk_label_new("?");
891 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_d_lb, 2, 3, 5, 6);
892 gtk_widget_show(select_user_range_d_lb);
896 select_user_range_entry = gtk_entry_new();
897 gtk_entry_set_max_length (GTK_ENTRY (select_user_range_entry), 254);
898 gtk_table_attach_defaults(GTK_TABLE(range_tb), select_user_range_entry, 0, 1, 6, 7);
899 gtk_tooltips_set_tip (tooltips,select_user_range_entry,
900 ("Specify a range of packet numbers : \nExample : 1-10,18,25-100,332-"), NULL);
901 SIGNAL_CONNECT(select_user_range_entry,"changed", range_entry, select_user_range_entry);
902 gtk_widget_set_sensitive(select_user_range_entry, FALSE);
903 gtk_widget_show(select_user_range_entry);
905 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(captured_bt), TRUE);
906 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayed_bt), FALSE);
907 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(select_all_rb), TRUE);
910 ft_hb = gtk_hbox_new(FALSE, 3);
911 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
912 gtk_widget_show(ft_hb);
914 ft_lb = gtk_label_new("File type:");
915 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
916 gtk_widget_show(ft_lb);
918 ft_om = gtk_option_menu_new();
920 /* Generate the list of file types we can save. */
921 set_file_type_list(ft_om);
922 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
923 gtk_widget_show(ft_om);
926 * Set the sensitivity of the "Save only marked packets" toggle
929 * This has to be done after we create the file type menu option,
930 * as the routine that sets it also sets that menu.
932 file_set_save_marked_sensitive();
934 /* dynamic values in the range frame */
935 file_set_save_dynamics();
937 /* Connect the cancel_button to destroy the widget */
938 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_save_as_w)->cancel_button,
939 "clicked", (GtkSignalFunc)gtk_widget_destroy,
942 /* Catch the "key_press_event" signal in the window, so that we can catch
943 the ESC key being pressed and act as if the "Cancel" button had
945 dlg_set_cancel(file_save_as_w, GTK_FILE_SELECTION(file_save_as_w)->cancel_button);
947 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_save_as_w), "");
949 gtk_widget_show(file_save_as_w);
953 file_save_as_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
958 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
960 /* Perhaps the user specified a directory instead of a file.
961 Check whether they did. */
962 if (test_for_directory(cf_name) == EISDIR) {
963 /* It's a directory - set the file selection box to display that
964 directory, and leave the selection box displayed. */
965 set_last_open_dir(cf_name);
967 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
971 /* don't show the dialog while saving */
972 gtk_widget_hide(GTK_WIDGET (fs));
974 /* Write out the packets (all, or only the ones from the current
975 range) to the file with the specified name. */
976 if (! cf_save(cf_name, &cfile, &range, filetype)) {
977 /* The write failed; don't dismiss the open dialog box,
978 just leave it around so that the user can, after they
979 dismiss the alert box popped up for the error, try again. */
981 gtk_widget_show(GTK_WIDGET (fs));
985 /* The write succeeded; get rid of the file selection box. */
986 gtk_widget_destroy(GTK_WIDGET (fs));
988 /* Save the directory name for future file dialogs. */
989 dirname = get_dirname(cf_name); /* Overwrites cf_name */
990 set_last_open_dir(dirname);
995 file_save_as_destroy(void)
998 gtk_widget_destroy(file_save_as_w);
1002 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1004 /* Note that we no longer have a "Save Capture File As" dialog box. */
1005 file_save_as_w = NULL;
1008 /* Reload a file using the current read and display filters */
1010 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1012 gboolean is_tempfile;
1015 /* If the file could be opened, "cf_open()" calls "cf_close()"
1016 to get rid of state for the old capture file before filling in state
1017 for the new capture file. "cf_close()" will remove the file if
1018 it's a temporary file; we don't want that to happen (for one thing,
1019 it'd prevent subsequent reopens from working). Remember whether it's
1020 a temporary file, mark it as not being a temporary file, and then
1021 reopen it as the type of file it was.
1023 Also, "cf_close()" will free "cfile.filename", so we must make
1024 a copy of it first. */
1025 filename = g_strdup(cfile.filename);
1026 is_tempfile = cfile.is_tempfile;
1027 cfile.is_tempfile = FALSE;
1028 if (cf_open(filename, is_tempfile, &cfile) == 0) {
1029 switch (cf_read(&cfile, &err)) {
1033 /* Just because we got an error, that doesn't mean we were unable
1034 to read any of the file; we handle what we could get from the
1039 /* The user bailed out of re-reading the capture file; the
1040 capture file has been closed - just free the capture file name
1041 string and return (without changing the last containing
1047 /* The open failed, so "cfile.is_tempfile" wasn't set to "is_tempfile".
1048 Instead, the file was left open, so we should restore "cfile.is_tempfile"
1051 XXX - change the menu? Presumably "cf_open()" will do that;
1052 make sure it does! */
1053 cfile.is_tempfile = is_tempfile;
1055 /* "cf_open()" made a copy of the file name we handed it, so
1056 we should free up our copy. */
1060 /******************** Color Filters *********************************/
1062 * Keep a static pointer to the current "Color Export" window, if
1063 * any, so that if somebody tries to do "Export"
1064 * while there's already a "Color Export" window up, we just pop
1065 * up the existing one, rather than creating a new one.
1067 static GtkWidget *file_color_import_w;
1069 /* sets the file path to the global color filter file.
1070 WARNING: called by both the import and the export dialog.
1073 color_global_cb(GtkWidget *widget _U_, gpointer data)
1075 GtkWidget *fs_widget = data;
1079 /* decide what file to open (from dfilter code) */
1080 path = get_datafile_path("colorfilters");
1082 gtk_file_selection_set_filename (GTK_FILE_SELECTION(fs_widget), path);
1084 g_free((gchar *)path);
1087 /* Import color filters */
1089 file_color_import_cmd_cb(GtkWidget *w _U_, gpointer data)
1091 GtkWidget *main_vb, *cfglobal_but;
1092 #if GTK_MAJOR_VERSION < 2
1093 GtkAccelGroup *accel_group;
1095 /* No Apply button, and "OK" just sets our text widget, it doesn't
1096 activate it (i.e., it doesn't cause us to try to open the file). */
1098 if (file_color_import_w != NULL) {
1099 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1100 reactivate_window(file_color_import_w);
1104 file_color_import_w = gtk_file_selection_new ("Ethereal: Import Color Filters");
1105 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1107 #if GTK_MAJOR_VERSION < 2
1108 /* Accelerator group for the accelerators (or, as they're called in
1109 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
1110 Ctrl+<key> is an accelerator). */
1111 accel_group = gtk_accel_group_new();
1112 gtk_window_add_accel_group(GTK_WINDOW(file_color_import_w), accel_group);
1115 /* If we've opened a file, start out by showing the files in the directory
1116 in which that file resided. */
1118 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_import_w), last_open_dir);
1120 /* Container for each row of widgets */
1121 main_vb = gtk_vbox_new(FALSE, 3);
1122 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1123 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_import_w)->action_area),
1124 main_vb, FALSE, FALSE, 0);
1125 gtk_widget_show(main_vb);
1128 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1129 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1130 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1131 gtk_widget_show(cfglobal_but);
1133 /* Connect the ok_button to file_open_ok_cb function and pass along a
1134 pointer to the file selection box widget */
1135 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1136 file_color_import_ok_cb, file_color_import_w);
1138 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_color_import_w)->ok_button,
1141 /* Connect the cancel_button to destroy the widget */
1142 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_import_w)->cancel_button,
1143 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1144 file_color_import_w);
1146 /* Catch the "key_press_event" signal in the window, so that we can catch
1147 the ESC key being pressed and act as if the "Cancel" button had
1149 dlg_set_cancel(file_color_import_w, GTK_FILE_SELECTION(file_color_import_w)->cancel_button);
1151 gtk_widget_show(file_color_import_w);
1155 file_color_import_ok_cb(GtkWidget *w, GtkFileSelection *fs) {
1159 argument = OBJECT_GET_DATA(w, ARGUMENT_CL); /* to be passed back into read_other_filters */
1161 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION (fs)));
1162 /* Perhaps the user specified a directory instead of a file.
1163 Check whether they did. */
1164 if (test_for_directory(cf_name) == EISDIR) {
1165 /* It's a directory - set the file selection box to display that
1166 directory, don't try to open the directory as a capture file. */
1167 set_last_open_dir(cf_name);
1169 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1173 /* Try to open the capture file. */
1175 if (!read_other_filters(cf_name, argument)) {
1176 /* We couldn't open it; don't dismiss the open dialog box,
1177 just leave it around so that the user can, after they
1178 dismiss the alert box popped up for the open error,
1184 /* We've crossed the Rubicon; get rid of the file selection box. */
1185 gtk_widget_hide(GTK_WIDGET (fs));
1186 gtk_widget_destroy(GTK_WIDGET (fs));
1188 /* Save the name of the containing directory specified in the path name,
1189 if any; we can write over cf_name, which is a good thing, given that
1190 "get_dirname()" does write over its argument. */
1191 s = get_dirname(cf_name);
1192 set_last_open_dir(s);
1193 gtk_widget_grab_focus(packet_list);
1199 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1201 /* Note that we no longer have a "Open Capture File" dialog box. */
1202 file_color_import_w = NULL;
1205 static GtkWidget *file_color_export_w;
1207 * Set the "Export only marked filters" toggle button as appropriate for
1208 * the current output file type and count of marked filters.
1210 * Called when the "Export" dialog box is created and when the marked
1214 color_set_export_marked_sensitive(GtkWidget * cfmark_cb)
1216 if (file_color_export_w == NULL) {
1217 /* We don't currently have an "Export" dialog box up. */
1221 /* We can request that only the marked filters be saved only if
1222 there *are* marked filters. */
1223 if (color_marked_count() != 0)
1224 gtk_widget_set_sensitive(cfmark_cb, TRUE);
1226 /* Force the "Export only marked filters" toggle to "false", turn
1227 off the flag it controls. */
1228 color_marked = FALSE;
1229 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1230 gtk_widget_set_sensitive(cfmark_cb, FALSE);
1235 color_toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
1237 color_marked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1241 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1243 GtkWidget *ok_bt, *main_vb, *cfglobal_but;
1245 if (file_color_export_w != NULL) {
1246 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1247 reactivate_window(file_color_export_w);
1251 /* Default to saving all packets, in the file's current format. */
1252 color_marked = FALSE;
1253 filetype = cfile.cd_t;
1255 file_color_export_w = gtk_file_selection_new ("Ethereal: Export Color Filters");
1256 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1258 /* If we've opened a file, start out by showing the files in the directory
1259 in which that file resided. */
1261 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), last_open_dir);
1263 /* Connect the ok_button to file_export_ok_cb function and pass along a
1264 pointer to the file selection box widget */
1265 ok_bt = GTK_FILE_SELECTION (file_color_export_w)->ok_button;
1266 SIGNAL_CONNECT(ok_bt, "clicked", file_color_export_ok_cb, file_color_export_w);
1268 /* Container for each row of widgets */
1269 main_vb = gtk_vbox_new(FALSE, 3);
1270 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1271 gtk_box_pack_start(GTK_BOX(GTK_FILE_SELECTION(file_color_export_w)->action_area),
1272 main_vb, FALSE, FALSE, 0);
1273 gtk_widget_show(main_vb);
1275 cfmark_cb = gtk_check_button_new_with_label("Export only marked filters");
1276 gtk_container_add(GTK_CONTAINER(main_vb), cfmark_cb);
1277 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1278 SIGNAL_CONNECT(cfmark_cb, "toggled", color_toggle_marked_cb, NULL);
1279 gtk_widget_show(cfmark_cb);
1280 color_set_export_marked_sensitive(cfmark_cb);
1282 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1283 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1284 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1285 gtk_widget_show(cfglobal_but);
1287 /* Connect the cancel_button to destroy the widget */
1288 SIGNAL_CONNECT_OBJECT(GTK_FILE_SELECTION(file_color_export_w)->cancel_button,
1289 "clicked", (GtkSignalFunc)gtk_widget_destroy,
1290 file_color_export_w);
1292 /* Catch the "key_press_event" signal in the window, so that we can catch
1293 the ESC key being pressed and act as if the "Cancel" button had
1295 dlg_set_cancel(file_color_export_w, GTK_FILE_SELECTION(file_color_export_w)->cancel_button);
1297 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1299 gtk_widget_show(file_color_export_w);
1303 file_color_export_ok_cb(GtkWidget *w _U_, GtkFileSelection *fs) {
1307 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1309 /* Perhaps the user specified a directory instead of a file.
1310 Check whether they did. */
1311 if (test_for_directory(cf_name) == EISDIR) {
1312 /* It's a directory - set the file selection box to display that
1313 directory, and leave the selection box displayed. */
1314 set_last_open_dir(cf_name);
1316 gtk_file_selection_set_filename(GTK_FILE_SELECTION(fs), last_open_dir);
1320 /* Write out the filters (all, or only the ones that are currently
1321 displayed or marked) to the file with the specified name. */
1323 if (!write_other_filters(cf_name, color_marked))
1325 /* The write failed; don't dismiss the open dialog box,
1326 just leave it around so that the user can, after they
1327 dismiss the alert box popped up for the error, try again. */
1333 /* The write succeeded; get rid of the file selection box. */
1334 gtk_widget_hide(GTK_WIDGET (fs));
1335 gtk_widget_destroy(GTK_WIDGET (fs));
1337 /* Save the directory name for future file dialogs. */
1338 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1339 set_last_open_dir(dirname);
1344 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1346 file_color_export_w = NULL;