2 * Dialog boxes for handling files
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.
33 #include "packet-range.h"
34 #include <epan/filesystem.h>
37 #include "gtkglobals.h"
38 #include <epan/addr_resolv.h>
40 #include "filter_dlg.h"
42 #include "alert_box.h"
43 #include "simple_dialog.h"
45 #include "dlg_utils.h"
48 #include "compat_macros.h"
49 #include <epan/prefs.h>
52 #include "../ui_util.h"
53 #include "color_filters.h"
54 #include "gtk/color_dlg.h"
56 #include "capture_dlg.h"
57 #include "range_utils.h"
67 #include <io.h> /* open/close on win32 */
70 static void file_open_ok_cb(GtkWidget *w, gpointer fs);
71 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
72 static void file_merge_ok_cb(GtkWidget *w, gpointer fs);
73 static void file_merge_destroy_cb(GtkWidget *win, gpointer user_data);
74 static void select_file_type_cb(GtkWidget *w, gpointer data);
75 static void file_save_as_ok_cb(GtkWidget *w, gpointer fs);
76 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
77 static void file_color_import_ok_cb(GtkWidget *w, gpointer fs);
78 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
79 static void file_color_export_ok_cb(GtkWidget *w, gpointer fs);
80 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
82 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
83 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
84 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
86 #define E_MERGE_PREPEND_KEY "merge_dlg_prepend_key"
87 #define E_MERGE_CHRONO_KEY "merge_dlg_chrono_key"
88 #define E_MERGE_APPEND_KEY "merge_dlg_append_key"
90 #define ARGUMENT_CL "argument_cl"
93 #define PREVIEW_TABLE_KEY "preview_table_key"
94 #define PREVIEW_FILENAME_KEY "preview_filename_key"
95 #define PREVIEW_FORMAT_KEY "preview_format_key"
96 #define PREVIEW_SIZE_KEY "preview_size_key"
97 #define PREVIEW_ELAPSED_KEY "preview_elapsed_key"
98 #define PREVIEW_PACKETS_KEY "preview_packets_key"
99 #define PREVIEW_FIRST_KEY "preview_first_key"
103 * Keep a static pointer to the current "Save Capture File As" window, if
104 * any, so that if somebody tries to do "File:Save" or "File:Save As"
105 * while there's already a "Save Capture File As" window up, we just pop
106 * up the existing one, rather than creating a new one.
108 static GtkWidget *file_save_as_w;
111 #ifdef HAVE_SYS_STAT_H
112 #include <sys/stat.h>
115 #define PREVIEW_STR_MAX 200
118 secs_usecs( guint32 s, guint32 us)
120 return (us / 1000000.0) + (double)s;
124 /* set a new filename for the preview widget */
126 preview_set_filename(GtkWidget *prev, const gchar *cf_name)
133 gchar string_buff[PREVIEW_STR_MAX];
137 /* init preview labels */
138 label = OBJECT_GET_DATA(prev, PREVIEW_FILENAME_KEY);
139 gtk_label_set_text(GTK_LABEL(label), "-");
140 label = OBJECT_GET_DATA(prev, PREVIEW_FORMAT_KEY);
141 gtk_label_set_text(GTK_LABEL(label), "-");
142 label = OBJECT_GET_DATA(prev, PREVIEW_SIZE_KEY);
143 gtk_label_set_text(GTK_LABEL(label), "-");
144 label = OBJECT_GET_DATA(prev, PREVIEW_ELAPSED_KEY);
145 gtk_label_set_text(GTK_LABEL(label), "-");
146 label = OBJECT_GET_DATA(prev, PREVIEW_PACKETS_KEY);
147 gtk_label_set_text(GTK_LABEL(label), "-");
148 label = OBJECT_GET_DATA(prev, PREVIEW_FIRST_KEY);
149 gtk_label_set_text(GTK_LABEL(label), "-");
155 label = OBJECT_GET_DATA(prev, PREVIEW_FILENAME_KEY);
156 gtk_label_set_text(GTK_LABEL(label), get_basename((char *)cf_name));
158 if (test_for_directory(cf_name) == EISDIR) {
159 label = OBJECT_GET_DATA(prev, PREVIEW_FORMAT_KEY);
160 gtk_label_set_text(GTK_LABEL(label), "directory");
164 wth = wtap_open_offline(cf_name, &err, &err_info, TRUE);
166 label = OBJECT_GET_DATA(prev, PREVIEW_FORMAT_KEY);
167 if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
168 gtk_label_set_text(GTK_LABEL(label), "unknown file format");
170 gtk_label_set_text(GTK_LABEL(label), "error opening file");
175 /* Find the size of the file. */
176 if (fstat(wtap_fd(wth), &cf_stat) < 0) {
182 filesize = cf_stat.st_size;
183 g_snprintf(string_buff, PREVIEW_STR_MAX, "%" PRIu64 " bytes", filesize);
184 label = OBJECT_GET_DATA(prev, PREVIEW_SIZE_KEY);
185 gtk_label_set_text(GTK_LABEL(label), string_buff);
188 g_snprintf(string_buff, PREVIEW_STR_MAX, "%s", wtap_file_type_string(wtap_file_type(wth)));
189 label = OBJECT_GET_DATA(prev, PREVIEW_FORMAT_KEY);
190 gtk_label_set_text(GTK_LABEL(label), string_buff);
196 /* do a preview run on the currently selected capture file */
198 preview_do(GtkWidget *prev, wtap *wth)
201 unsigned int elapsed_time;
207 const struct wtap_pkthdr *phdr;
208 double start_time = 0; /* seconds, with msec resolution */
209 double stop_time = 0; /* seconds, with msec resolution */
211 unsigned int packets = 0;
212 gboolean is_breaked = FALSE;
213 gchar string_buff[PREVIEW_STR_MAX];
219 while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
220 phdr = wtap_phdr(wth);
221 cur_time = secs_usecs(phdr->ts.tv_sec, phdr->ts.tv_usec);
223 start_time = cur_time;
224 stop_time = cur_time;
226 if (cur_time < start_time) {
227 start_time = cur_time;
229 if (cur_time > stop_time){
230 stop_time = cur_time;
235 /* do we have a timeout? */
237 if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
245 g_snprintf(string_buff, PREVIEW_STR_MAX, "error after reading %u packets", packets);
246 label = OBJECT_GET_DATA(prev, PREVIEW_PACKETS_KEY);
247 gtk_label_set_text(GTK_LABEL(label), string_buff);
254 g_snprintf(string_buff, PREVIEW_STR_MAX, "more than %u packets (preview timeout)", packets);
256 g_snprintf(string_buff, PREVIEW_STR_MAX, "%u", packets);
258 label = OBJECT_GET_DATA(prev, PREVIEW_PACKETS_KEY);
259 gtk_label_set_text(GTK_LABEL(label), string_buff);
262 ti_time = (long)start_time;
263 ti_tm = localtime( &ti_time );
264 g_snprintf(string_buff, PREVIEW_STR_MAX,
265 "%04d-%02d-%02d %02d:%02d:%02d",
266 ti_tm->tm_year + 1900,
272 label = OBJECT_GET_DATA(prev, PREVIEW_FIRST_KEY);
273 gtk_label_set_text(GTK_LABEL(label), string_buff);
276 elapsed_time = (unsigned int)(stop_time-start_time);
277 if(elapsed_time/86400) {
278 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u days %02u:%02u:%02u",
279 elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
281 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u:%02u:%02u",
282 elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
285 g_snprintf(string_buff, PREVIEW_STR_MAX, "unknown");
287 label = OBJECT_GET_DATA(prev, PREVIEW_ELAPSED_KEY);
288 gtk_label_set_text(GTK_LABEL(label), string_buff);
294 /* as the dialog layout will look very ugly when using the file chooser preview mechanism,
295 simply use the same layout as in GTK1 */
296 /* (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2 */
298 update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
300 GtkWidget *prev = GTK_WIDGET (data);
302 gboolean have_preview;
304 cf_name = gtk_file_chooser_get_preview_filename (file_chooser);
306 have_preview = preview_set_filename(prev, cf_name);
311 gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
316 /* the filename text entry changed */
318 file_open_entry_changed(GtkWidget *w _U_, gpointer file_sel)
320 GtkWidget *prev = OBJECT_GET_DATA(file_sel, PREVIEW_TABLE_KEY);
321 const gchar* cf_name;
322 gboolean have_preview;
325 /* get the filename */
326 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
327 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_sel));
329 cf_name = gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_sel));
332 /* set the filename to the preview */
333 wth = preview_set_filename(prev, cf_name);
334 have_preview = (gboolean) wth;
336 /* make the preview widget sensitive */
337 gtk_widget_set_sensitive(prev, have_preview);
339 /* make the open/save/... dialog button sensitive */
340 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
341 gtk_dialog_set_response_sensitive(file_sel, GTK_RESPONSE_ACCEPT, have_preview);
343 gtk_widget_set_sensitive(GTK_FILE_SELECTION(file_sel)->ok_button, have_preview);
346 /* do the actual preview */
348 preview_do(prev, wth);
352 /* copied from summary_dlg.c */
354 add_string_to_table_sensitive(GtkWidget *list, guint *row, gchar *title, gchar *value, gboolean sensitive)
359 if(strlen(value) != 0) {
360 indent = g_strdup_printf(" %s", title);
362 indent = g_strdup(title);
364 label = gtk_label_new(indent);
366 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
367 gtk_widget_set_sensitive(label, sensitive);
368 gtk_table_attach_defaults(GTK_TABLE(list), label, 0, 1, *row, *row+1);
370 label = gtk_label_new(value);
371 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
372 gtk_widget_set_sensitive(label, sensitive);
373 gtk_table_attach_defaults(GTK_TABLE(list), label, 1, 2, *row, *row+1);
381 add_string_to_table(GtkWidget *list, guint *row, gchar *title, gchar *value)
383 return add_string_to_table_sensitive(list, row, title, value, TRUE);
391 GtkWidget *table, *label;
394 table = gtk_table_new(1, 2, FALSE);
395 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
396 gtk_table_set_row_spacings(GTK_TABLE(table), 3);
399 label = add_string_to_table(table, &row, "Filename:", "-");
400 WIDGET_SET_SIZE(label, DEF_WIDTH/3, -1);
401 OBJECT_SET_DATA(table, PREVIEW_FILENAME_KEY, label);
402 label = add_string_to_table(table, &row, "Format:", "-");
403 OBJECT_SET_DATA(table, PREVIEW_FORMAT_KEY, label);
404 label = add_string_to_table(table, &row, "Size:", "-");
405 OBJECT_SET_DATA(table, PREVIEW_SIZE_KEY, label);
406 label = add_string_to_table(table, &row, "Packets:", "-");
407 OBJECT_SET_DATA(table, PREVIEW_PACKETS_KEY, label);
408 label = add_string_to_table(table, &row, "First Packet:", "-");
409 OBJECT_SET_DATA(table, PREVIEW_FIRST_KEY, label);
410 label = add_string_to_table(table, &row, "Elapsed time:", "-");
411 OBJECT_SET_DATA(table, PREVIEW_ELAPSED_KEY, label);
417 * Keep a static pointer to the current "Open Capture File" window, if
418 * any, so that if somebody tries to do "File:Open" while there's already
419 * an "Open Capture File" window up, we just pop up the existing one,
420 * rather than creating a new one.
422 static GtkWidget *file_open_w;
426 file_open_cmd(GtkWidget *w)
428 GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te,
429 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, *prev;
430 #if GTK_MAJOR_VERSION < 2
431 GtkAccelGroup *accel_group;
433 /* No Apply button, and "OK" just sets our text widget, it doesn't
434 activate it (i.e., it doesn't cause us to try to open the file). */
435 static construct_args_t args = {
436 "Ethereal: Read Filter",
441 if (file_open_w != NULL) {
442 /* There's already an "Open Capture File" dialog box; reactivate it. */
443 reactivate_window(file_open_w);
447 file_open_w = file_selection_new("Ethereal: Open Capture File",
448 FILE_SELECTION_OPEN);
449 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
450 /* it's annoying, that the file chooser dialog is already shown here,
451 so we cannot use the correct gtk_window_set_default_size() to resize it */
452 WIDGET_SET_SIZE(GTK_WINDOW(file_open_w), DEF_WIDTH, DEF_HEIGHT);
454 gtk_window_set_default_size(GTK_WINDOW(file_open_w), DEF_WIDTH, DEF_HEIGHT);
457 #if GTK_MAJOR_VERSION < 2
458 /* Accelerator group for the accelerators (or, as they're called in
459 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
460 Ctrl+<key> is an accelerator). */
461 accel_group = gtk_accel_group_new();
462 gtk_window_add_accel_group(GTK_WINDOW(file_open_w), accel_group);
465 switch (prefs.gui_fileopen_style) {
467 case FO_STYLE_LAST_OPENED:
468 /* The user has specified that we should start out in the last directory
469 we looked in. If we've already opened a file, use its containing
470 directory, if we could determine it, as the directory, otherwise
471 use the "last opened" directory saved in the preferences file if
473 /* This is now the default behaviour in file_selection_new() */
476 case FO_STYLE_SPECIFIED:
477 /* The user has specified that we should always start out in a
478 specified directory; if they've specified that directory,
479 start out by showing the files in that dir. */
480 if (prefs.gui_fileopen_dir[0] != '\0')
481 file_selection_set_current_folder(file_open_w, prefs.gui_fileopen_dir);
486 main_hb = gtk_hbox_new(FALSE, 3);
487 file_selection_set_extra_widget(file_open_w, main_hb);
488 gtk_widget_show(main_hb);
490 /* Container for each row of widgets */
491 main_vb = gtk_vbox_new(FALSE, 3);
492 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
493 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
494 gtk_widget_show(main_vb);
497 filter_hbox = gtk_hbox_new(FALSE, 1);
498 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
499 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
500 gtk_widget_show(filter_hbox);
502 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
503 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
504 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
505 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
506 gtk_widget_show(filter_bt);
508 filter_te = gtk_entry_new();
509 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
510 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
511 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
512 gtk_widget_show(filter_te);
514 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
515 OBJECT_SET_DATA(file_open_w, E_RFILTER_TE_KEY, filter_te);
517 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
518 E_RFILTER_TE_KEY, filter_te);
521 /* resolve buttons */
522 m_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _MAC name resolution", accel_group);
523 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
524 g_resolv_flags & RESOLV_MAC);
525 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
526 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
527 OBJECT_SET_DATA(file_open_w,
528 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
530 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
531 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
533 gtk_widget_show(m_resolv_cb);
535 n_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _network name resolution", accel_group);
536 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
537 g_resolv_flags & RESOLV_NETWORK);
538 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
539 gtk_widget_show(n_resolv_cb);
540 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
541 OBJECT_SET_DATA(file_open_w, E_FILE_N_RESOLVE_KEY, n_resolv_cb);
543 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
544 E_FILE_N_RESOLVE_KEY, n_resolv_cb);
547 t_resolv_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Enable _transport name resolution", accel_group);
548 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
549 g_resolv_flags & RESOLV_TRANSPORT);
550 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
551 gtk_widget_show(t_resolv_cb);
552 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
553 OBJECT_SET_DATA(file_open_w, E_FILE_T_RESOLVE_KEY, t_resolv_cb);
555 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
556 E_FILE_T_RESOLVE_KEY, t_resolv_cb);
560 SIGNAL_CONNECT(file_open_w, "destroy", file_open_destroy_cb, NULL);
563 prev = preview_new();
564 OBJECT_SET_DATA(file_open_w, PREVIEW_TABLE_KEY, prev);
565 gtk_widget_show_all(prev);
566 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
568 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
569 SIGNAL_CONNECT(GTK_FILE_CHOOSER(file_open_w), "selection-changed",
570 file_open_entry_changed, file_open_w);
571 file_open_entry_changed(file_open_w, file_open_w);
573 OBJECT_SET_DATA(file_open_w, E_DFILTER_TE_KEY,
574 OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
575 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
577 file_open_ok_cb(file_open_w, file_open_w);
579 else window_destroy(file_open_w);
581 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->selection_entry, "changed",
582 file_open_entry_changed, file_open_w);
584 /* Connect the ok_button to file_open_ok_cb function and pass along a
585 pointer to the file selection box widget */
586 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_open_w)->ok_button, "clicked",
587 file_open_ok_cb, file_open_w);
589 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_open_w)->ok_button,
590 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
592 /* Connect the cancel_button to destroy the widget */
593 window_set_cancel_button(file_open_w,
594 GTK_FILE_SELECTION(file_open_w)->cancel_button, window_cancel_button_cb);
596 SIGNAL_CONNECT(file_open_w, "delete_event", window_delete_event_cb, NULL);
598 gtk_widget_show(file_open_w);
599 window_present(file_open_w);
603 static void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
607 /* save file first */
608 file_save_as_cmd(after_save_open_dialog, data);
610 case(ESD_BTN_DONT_SAVE):
614 case(ESD_BTN_CANCEL):
617 g_assert_not_reached();
622 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
625 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
626 /* user didn't saved his current file, ask him */
627 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
628 PRIMARY_TEXT_START "Save capture file before opening a new one?" PRIMARY_TEXT_END "\n\n"
629 "If you open a new capture file without saving, your capture data will be discarded.");
630 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
632 /* unchanged file, just open a new one */
633 file_open_cmd(widget);
637 /* user pressed "open" button */
639 file_open_ok_cb(GtkWidget *w, gpointer fs) {
640 gchar *cf_name, *rfilter, *s;
641 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
642 dfilter_t *rfcode = NULL;
645 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
646 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
648 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
650 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
651 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
652 if (!dfilter_compile(rfilter, &rfcode)) {
653 bad_dfilter_alert_box(rfilter);
658 /* Perhaps the user specified a directory instead of a file.
659 Check whether they did. */
660 if (test_for_directory(cf_name) == EISDIR) {
661 /* It's a directory - set the file selection box to display that
662 directory, don't try to open the directory as a capture file. */
663 set_last_open_dir(cf_name);
665 file_selection_set_current_folder(fs, get_last_open_dir());
669 /* Try to open the capture file. */
670 if ((err = cf_open(cf_name, FALSE, &cfile)) != 0) {
671 /* We couldn't open it; don't dismiss the open dialog box,
672 just leave it around so that the user can, after they
673 dismiss the alert box popped up for the open error,
676 dfilter_free(rfcode);
681 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
682 it closed the previous capture file, and thus destroyed any
683 previous read filter attached to "cf"). */
684 cfile.rfcode = rfcode;
686 /* Set the global resolving variable */
687 g_resolv_flags = prefs.name_resolve & RESOLV_CONCURRENT;
688 m_resolv_cb = OBJECT_GET_DATA(w, E_FILE_M_RESOLVE_KEY);
689 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)) ? RESOLV_MAC : RESOLV_NONE;
690 n_resolv_cb = OBJECT_GET_DATA(w, E_FILE_N_RESOLVE_KEY);
691 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)) ? RESOLV_NETWORK : RESOLV_NONE;
692 t_resolv_cb = OBJECT_GET_DATA(w, E_FILE_T_RESOLVE_KEY);
693 g_resolv_flags |= gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)) ? RESOLV_TRANSPORT : RESOLV_NONE;
695 /* We've crossed the Rubicon; get rid of the file selection box. */
696 window_destroy(GTK_WIDGET (fs));
698 switch (cf_read(&cfile)) {
702 /* Just because we got an error, that doesn't mean we were unable
703 to read any of the file; we handle what we could get from the
708 /* The user bailed out of re-reading the capture file; the
709 capture file has been closed - just free the capture file name
710 string and return (without changing the last containing
716 /* Save the name of the containing directory specified in the path name,
717 if any; we can write over cf_name, which is a good thing, given that
718 "get_dirname()" does write over its argument. */
719 s = get_dirname(cf_name);
720 set_last_open_dir(s);
721 gtk_widget_grab_focus(packet_list);
727 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
729 /* Note that we no longer have a "Open Capture File" dialog box. */
734 * Keep a static pointer to the current "Marge Capture File" window, if
735 * any, so that if somebody tries to do "File:Merge" while there's already
736 * an "Merge Capture File" window up, we just pop up the existing one,
737 * rather than creating a new one.
739 static GtkWidget *file_merge_w;
741 /* Merge existing with another file */
743 file_merge_cmd(GtkWidget *w)
745 GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te,
746 *prepend_rb, *chrono_rb, *append_rb, *prev;
747 #if GTK_MAJOR_VERSION < 2
748 GtkAccelGroup *accel_group;
750 GtkTooltips *tooltips = gtk_tooltips_new();
751 /* No Apply button, and "OK" just sets our text widget, it doesn't
752 activate it (i.e., it doesn't cause us to try to open the file). */
753 static construct_args_t args = {
754 "Ethereal: Read Filter",
759 if (file_merge_w != NULL) {
760 /* There's already an "Merge Capture File" dialog box; reactivate it. */
761 reactivate_window(file_merge_w);
765 file_merge_w = file_selection_new("Ethereal: Merge with Capture File",
766 FILE_SELECTION_OPEN);
767 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
768 /* it's annoying, that the file chooser dialog is already shown here,
769 so we cannot use the correct gtk_window_set_default_size() to resize it */
770 WIDGET_SET_SIZE(GTK_WINDOW(file_merge_w), DEF_WIDTH, DEF_HEIGHT);
772 gtk_window_set_default_size(GTK_WINDOW(file_merge_w), DEF_WIDTH, DEF_HEIGHT);
775 #if GTK_MAJOR_VERSION < 2
776 /* Accelerator group for the accelerators (or, as they're called in
777 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
778 Ctrl+<key> is an accelerator). */
779 accel_group = gtk_accel_group_new();
780 gtk_window_add_accel_group(GTK_WINDOW(file_merge_w), accel_group);
783 switch (prefs.gui_fileopen_style) {
785 case FO_STYLE_LAST_OPENED:
786 /* The user has specified that we should start out in the last directory
787 we looked in. If we've already opened a file, use its containing
788 directory, if we could determine it, as the directory, otherwise
789 use the "last opened" directory saved in the preferences file if
791 /* This is now the default behaviour in file_selection_new() */
794 case FO_STYLE_SPECIFIED:
795 /* The user has specified that we should always start out in a
796 specified directory; if they've specified that directory,
797 start out by showing the files in that dir. */
798 if (prefs.gui_fileopen_dir[0] != '\0')
799 file_selection_set_current_folder(file_merge_w, prefs.gui_fileopen_dir);
803 main_hb = gtk_hbox_new(FALSE, 3);
804 file_selection_set_extra_widget(file_merge_w, main_hb);
805 gtk_widget_show(main_hb);
807 /* Container for each row of widgets */
808 main_vb = gtk_vbox_new(FALSE, 3);
809 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
810 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
811 gtk_widget_show(main_vb);
813 filter_hbox = gtk_hbox_new(FALSE, 1);
814 gtk_container_border_width(GTK_CONTAINER(filter_hbox), 0);
815 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
816 gtk_widget_show(filter_hbox);
818 filter_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_DISPLAY_FILTER_ENTRY);
819 SIGNAL_CONNECT(filter_bt, "clicked", display_filter_construct_cb, &args);
820 SIGNAL_CONNECT(filter_bt, "destroy", filter_button_destroy_cb, NULL);
821 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
822 gtk_widget_show(filter_bt);
824 filter_te = gtk_entry_new();
825 OBJECT_SET_DATA(filter_bt, E_FILT_TE_PTR_KEY, filter_te);
826 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
827 SIGNAL_CONNECT(filter_te, "changed", filter_te_syntax_check_cb, NULL);
828 gtk_widget_show(filter_te);
830 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
831 OBJECT_SET_DATA(file_merge_w, E_RFILTER_TE_KEY, filter_te);
833 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_merge_w)->ok_button,
834 E_RFILTER_TE_KEY, filter_te);
837 prepend_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "Prepend packets to existing file", accel_group);
838 gtk_tooltips_set_tip(tooltips, prepend_rb,
839 "The resulting file contains the packets from the selected, followed by the packets from the currently loaded file,"
840 " the packet timestamps will be ignored.", NULL);
841 gtk_box_pack_start(GTK_BOX(main_vb), prepend_rb, FALSE, FALSE, 0);
842 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
843 OBJECT_SET_DATA(file_merge_w,
844 E_MERGE_PREPEND_KEY, prepend_rb);
846 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_merge_w)->ok_button,
847 E_MERGE_PREPEND_KEY, prepend_rb);
849 gtk_widget_show(prepend_rb);
851 chrono_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(prepend_rb, "Merge packets chronologically", accel_group);
852 gtk_tooltips_set_tip(tooltips, chrono_rb,
853 "The resulting file contains all the packets from the currently loaded and the selected file,"
854 " sorted by the packet timestamps.", NULL);
855 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chrono_rb), TRUE);
856 gtk_box_pack_start(GTK_BOX(main_vb), chrono_rb, FALSE, FALSE, 0);
857 gtk_widget_show(chrono_rb);
858 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
859 OBJECT_SET_DATA(file_merge_w, E_MERGE_CHRONO_KEY, chrono_rb);
861 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_merge_w)->ok_button,
862 E_MERGE_CHRONO_KEY, chrono_rb);
865 append_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(prepend_rb, "Append packets to existing file", accel_group);
866 gtk_tooltips_set_tip(tooltips, append_rb,
867 "The resulting file contains the packets from the currently loaded, followed by the packets from the selected file,"
868 " the packet timestamps will be ignored.", NULL);
869 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(append_rb),
870 g_resolv_flags & RESOLV_TRANSPORT);
871 gtk_box_pack_start(GTK_BOX(main_vb), append_rb, FALSE, FALSE, 0);
872 gtk_widget_show(append_rb);
873 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
874 OBJECT_SET_DATA(file_merge_w, E_MERGE_APPEND_KEY, append_rb);
876 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_merge_w)->ok_button,
877 E_MERGE_APPEND_KEY, append_rb);
881 SIGNAL_CONNECT(file_merge_w, "destroy", file_merge_destroy_cb, NULL);
884 prev = preview_new();
885 OBJECT_SET_DATA(file_merge_w, PREVIEW_TABLE_KEY, prev);
886 gtk_widget_show_all(prev);
887 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
889 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
890 SIGNAL_CONNECT(GTK_FILE_CHOOSER(file_merge_w), "selection-changed",
891 file_open_entry_changed, file_merge_w);
892 file_open_entry_changed(file_merge_w, file_merge_w);
894 OBJECT_SET_DATA(file_merge_w, E_DFILTER_TE_KEY,
895 OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
896 if (gtk_dialog_run(GTK_DIALOG(file_merge_w)) == GTK_RESPONSE_ACCEPT)
898 file_merge_ok_cb(file_merge_w, file_merge_w);
900 else window_destroy(file_merge_w);
902 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_merge_w)->selection_entry, "changed",
903 file_open_entry_changed, file_merge_w);
905 /* Connect the ok_button to file_merge_ok_cb function and pass along a
906 pointer to the file selection box widget */
907 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_merge_w)->ok_button, "clicked",
908 file_merge_ok_cb, file_merge_w);
910 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_merge_w)->ok_button,
911 E_DFILTER_TE_KEY, OBJECT_GET_DATA(w, E_DFILTER_TE_KEY));
913 /* Connect the cancel_button to destroy the widget */
914 window_set_cancel_button(file_merge_w,
915 GTK_FILE_SELECTION(file_merge_w)->cancel_button, window_cancel_button_cb);
917 SIGNAL_CONNECT(file_merge_w, "delete_event", window_delete_event_cb, NULL);
919 gtk_widget_show(file_merge_w);
920 window_present(file_merge_w);
924 static void file_merge_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
928 /* save file first */
929 file_save_as_cmd(after_save_merge_dialog, data);
931 case(ESD_BTN_CANCEL):
934 g_assert_not_reached();
939 file_merge_cmd_cb(GtkWidget *widget, gpointer data _U_) {
942 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
943 /* user didn't saved his current file, ask him */
944 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
945 PRIMARY_TEXT_START "Save the capture file before merging to another one?" PRIMARY_TEXT_END "\n\n"
946 "A temporary capture file cannot be merged.");
947 simple_dialog_set_cb(dialog, file_merge_answered_cb, widget);
949 /* unchanged file, just start to merge */
950 file_merge_cmd(widget);
956 file_merge_ok_cb(GtkWidget *w, gpointer fs) {
957 gchar *cf_name, *rfilter, *s;
958 GtkWidget *filter_te, *rb;
959 dfilter_t *rfcode = NULL;
962 char *in_filenames[2];
966 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
967 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
969 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
971 filter_te = OBJECT_GET_DATA(w, E_RFILTER_TE_KEY);
972 rfilter = (gchar *)gtk_entry_get_text(GTK_ENTRY(filter_te));
973 if (!dfilter_compile(rfilter, &rfcode)) {
974 bad_dfilter_alert_box(rfilter);
979 /* Perhaps the user specified a directory instead of a file.
980 Check whether they did. */
981 if (test_for_directory(cf_name) == EISDIR) {
982 /* It's a directory - set the file selection box to display that
983 directory, don't try to open the directory as a capture file. */
984 set_last_open_dir(cf_name);
986 file_selection_set_current_folder(fs, get_last_open_dir());
990 out_fd = create_tempfile(tmpname, sizeof tmpname, "ether");
992 /* merge or append the two files */
993 rb = OBJECT_GET_DATA(w, E_MERGE_CHRONO_KEY);
994 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
995 /* chonological order */
996 in_filenames[0] = cfile.filename;
997 in_filenames[1] = cf_name;
998 merge_ok = merge_n_files(out_fd, 2, in_filenames, FALSE, &err);
1000 rb = OBJECT_GET_DATA(w, E_MERGE_PREPEND_KEY);
1001 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
1003 in_filenames[0] = cfile.filename;
1004 in_filenames[1] = cf_name;
1005 merge_ok = merge_n_files(out_fd, 2, in_filenames, TRUE, &err);
1008 in_filenames[0] = cf_name;
1009 in_filenames[1] = cfile.filename;
1010 merge_ok = merge_n_files(out_fd, 2, in_filenames, TRUE, &err);
1018 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1019 "An error occurred while merging the files: %s.",
1020 wtap_strerror(err));
1023 dfilter_free(rfcode);
1029 /* We've crossed the Rubicon; get rid of the file selection box. */
1030 window_destroy(GTK_WIDGET (fs));
1032 /* Try to open the merged capture file. */
1033 if ((err = cf_open(tmpname, TRUE /* temporary file */, &cfile)) != 0) {
1034 /* We couldn't open it; don't dismiss the open dialog box,
1035 just leave it around so that the user can, after they
1036 dismiss the alert box popped up for the open error,
1039 dfilter_free(rfcode);
1043 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
1044 it closed the previous capture file, and thus destroyed any
1045 previous read filter attached to "cf"). */
1046 cfile.rfcode = rfcode;
1048 switch (cf_read(&cfile)) {
1052 /* Just because we got an error, that doesn't mean we were unable
1053 to read any of the file; we handle what we could get from the
1058 /* The user bailed out of re-reading the capture file; the
1059 capture file has been closed - just free the capture file name
1060 string and return (without changing the last containing
1065 /* Save the name of the containing directory specified in the path name,
1066 if any; we can write over cf_merged_name, which is a good thing, given that
1067 "get_dirname()" does write over its argument. */
1068 s = get_dirname(tmpname);
1069 set_last_open_dir(s);
1070 gtk_widget_grab_focus(packet_list);
1074 file_merge_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1076 /* Note that we no longer have a "Merge Capture File" dialog box. */
1077 file_merge_w = NULL;
1081 void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1085 /* save file first */
1086 file_save_as_cmd(after_save_close_file, NULL);
1088 case(ESD_BTN_DONT_SAVE):
1091 case(ESD_BTN_CANCEL):
1094 g_assert_not_reached();
1100 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
1103 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1104 /* user didn't saved his current file, ask him */
1105 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1106 PRIMARY_TEXT_START "Save capture file before closing it?" PRIMARY_TEXT_END "\n\n"
1107 "If you close without saving, your capture data will be discarded.");
1109 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
1111 /* unchanged file, just close it */
1117 file_save_cmd_cb(GtkWidget *w, gpointer data) {
1118 /* If the file's already been saved, do nothing. */
1119 if (cfile.user_saved)
1122 /* Do a "Save As". */
1123 file_save_as_cmd_cb(w, data);
1126 /* XXX - can we make these not be static? */
1127 static packet_range_t range;
1128 static gboolean color_marked;
1129 static int filetype;
1130 static GtkWidget *cfmark_cb;
1131 static GtkWidget *ft_om;
1132 static GtkWidget *range_tb;
1135 can_save_with_wiretap(int ft)
1137 /* To save a file with Wiretap, Wiretap has to handle that format,
1138 and its code to handle that format must be able to write a file
1139 with this file's encapsulation type. */
1140 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
1144 /* Generate a list of the file types we can save this file as.
1146 "filetype" is the type it has now.
1148 "encap" is the encapsulation for its packets (which could be
1149 "unknown" or "per-packet").
1151 "filtered" is TRUE if we're to save only the packets that passed
1152 the display filter (in which case we have to save it using Wiretap)
1153 and FALSE if we're to save the entire file (in which case, if we're
1154 saving it in the type it has already, we can just copy it).
1156 The same applies for sel_curr, sel_all, sel_m_only, sel_m_range and sel_man_range
1159 set_file_type_list(GtkWidget *option_menu)
1161 GtkWidget *ft_menu, *ft_menu_item;
1164 guint item_to_select;
1166 /* Default to the first supported file type, if the file's current
1167 type isn't supported. */
1170 ft_menu = gtk_menu_new();
1172 /* Check all file types. */
1174 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1175 if (!packet_range_process_all(&range) || ft != cfile.cd_t) {
1176 /* not all unfiltered packets or a different file type. We have to use Wiretap. */
1177 if (!can_save_with_wiretap(ft))
1178 continue; /* We can't. */
1181 /* OK, we can write it out in this type. */
1182 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
1183 if (ft == filetype) {
1184 /* Default to the same format as the file, if it's supported. */
1185 item_to_select = index;
1187 SIGNAL_CONNECT(ft_menu_item, "activate", select_file_type_cb,
1188 GINT_TO_POINTER(ft));
1189 gtk_menu_append(GTK_MENU(ft_menu), ft_menu_item);
1190 gtk_widget_show(ft_menu_item);
1194 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
1195 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
1199 select_file_type_cb(GtkWidget *w _U_, gpointer data)
1201 int new_filetype = GPOINTER_TO_INT(data);
1203 if (filetype != new_filetype) {
1204 /* We can select only the filtered or marked packets to be saved if we can
1205 use Wiretap to save the file. */
1206 range_set_displayed_sensitive(range_tb, can_save_with_wiretap(new_filetype));
1207 filetype = new_filetype;
1208 file_set_save_marked_sensitive();
1214 * Set the "Save only marked packets" toggle button as appropriate for
1215 * the current output file type and count of marked packets.
1217 * Called when the "Save As..." dialog box is created and when either
1218 * the file type or the marked count changes.
1221 file_set_save_marked_sensitive(void)
1223 if (file_save_as_w == NULL) {
1224 /* We don't currently have a "Save As..." dialog box up. */
1228 /* We can request that only the marked packets be saved only if we
1229 can use Wiretap to save the file and if there *are* marked packets. */
1230 if (can_save_with_wiretap(filetype) && cfile.marked_count > 0) {
1231 range_set_marked_sensitive(range_tb, TRUE);
1234 /* Force the "Save only marked packets" toggle to "false", turn
1235 off the flag it controls, and update the list of types we can
1236 save the file as. */
1237 range.process = range_process_all;
1238 set_file_type_list(ft_om);
1239 range_set_marked_sensitive(range_tb, FALSE);
1244 action_after_save_e action_after_save_g;
1245 gpointer action_after_save_data_g;
1249 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
1251 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr;
1252 GtkTooltips *tooltips;
1254 #if GTK_MAJOR_VERSION < 2
1255 GtkAccelGroup *accel_group;
1258 if (file_save_as_w != NULL) {
1259 /* There's already an "Save Capture File As" dialog box; reactivate it. */
1260 reactivate_window(file_save_as_w);
1264 /* Default to saving all packets, in the file's current format. */
1265 filetype = cfile.cd_t;
1267 /* init the packet range */
1268 packet_range_init(&range);
1270 /* Enable tooltips */
1271 tooltips = gtk_tooltips_new();
1273 /* build the file selection */
1274 file_save_as_w = file_selection_new ("Ethereal: Save Capture File As",
1275 FILE_SELECTION_SAVE);
1277 /* as the dialog might already be gone, when using this values, we cannot
1278 * set data to the dialog object, but keep global values */
1279 action_after_save_g = action_after_save;
1280 action_after_save_data_g = action_after_save_data;
1282 #if GTK_MAJOR_VERSION < 2
1283 accel_group = gtk_accel_group_new();
1284 gtk_window_add_accel_group(GTK_WINDOW(file_save_as_w), accel_group);
1287 /* Container for each row of widgets */
1289 main_vb = gtk_vbox_new(FALSE, 5);
1290 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1291 file_selection_set_extra_widget(file_save_as_w, main_vb);
1292 gtk_widget_show(main_vb);
1294 /*** Packet Range frame ***/
1295 range_fr = gtk_frame_new("Packet Range");
1296 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
1297 gtk_widget_show(range_fr);
1300 range_tb = range_new(&range
1301 #if GTK_MAJOR_VERSION < 2
1305 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
1306 gtk_widget_show(range_tb);
1309 ft_hb = gtk_hbox_new(FALSE, 3);
1310 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1311 gtk_widget_show(ft_hb);
1313 ft_lb = gtk_label_new("File type:");
1314 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1315 gtk_widget_show(ft_lb);
1317 ft_om = gtk_option_menu_new();
1319 /* Generate the list of file types we can save. */
1320 set_file_type_list(ft_om);
1321 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1322 gtk_widget_show(ft_om);
1325 * Set the sensitivity of the "Save only marked packets" toggle
1328 * This has to be done after we create the file type menu option,
1329 * as the routine that sets it also sets that menu.
1331 file_set_save_marked_sensitive();
1333 /* dynamic values in the range frame */
1334 range_update_dynamics(range_tb);
1336 SIGNAL_CONNECT(file_save_as_w, "destroy", file_save_as_destroy_cb, NULL);
1338 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1339 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT) {
1340 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1342 window_destroy(file_save_as_w);
1345 /* Connect the ok_button to file_save_as_ok_cb function and pass along a
1346 pointer to the file selection box widget */
1347 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_save_as_w)->ok_button, "clicked",
1348 file_save_as_ok_cb, file_save_as_w);
1350 window_set_cancel_button(file_save_as_w,
1351 GTK_FILE_SELECTION(file_save_as_w)->cancel_button, window_cancel_button_cb);
1353 SIGNAL_CONNECT(file_save_as_w, "delete_event", window_delete_event_cb, NULL);
1355 gtk_widget_show(file_save_as_w);
1356 window_present(file_save_as_w);
1361 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1363 file_save_as_cmd(after_save_no_action, NULL);
1367 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1371 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1372 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1374 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1377 /* Perhaps the user specified a directory instead of a file.
1378 Check whether they did. */
1379 if (test_for_directory(cf_name) == EISDIR) {
1380 /* It's a directory - set the file selection box to display that
1381 directory, and leave the selection box displayed. */
1382 set_last_open_dir(cf_name);
1384 file_selection_set_current_folder(fs, get_last_open_dir());
1388 /* Check whether the range is valid. */
1389 if (!range_check_validity(&range)) {
1390 /* The range isn't valid; don't dismiss the open dialog box,
1391 just leave it around so that the user can, after they
1392 dismiss the alert box popped up for the error, try again. */
1394 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1395 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1396 * as this will prevent the user from closing the now existing error
1397 * message, simply close the dialog (this is the best we can do here). */
1399 window_destroy(GTK_WIDGET (fs));
1401 gtk_widget_show(GTK_WIDGET (fs));
1406 /* don't show the dialog while saving */
1407 gtk_widget_hide(GTK_WIDGET (fs));
1409 /* Write out the packets (all, or only the ones from the current
1410 range) to the file with the specified name. */
1411 if (! cf_save(cf_name, &cfile, &range, filetype)) {
1412 /* The write failed; don't dismiss the open dialog box,
1413 just leave it around so that the user can, after they
1414 dismiss the alert box popped up for the error, try again. */
1416 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1417 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1418 * as this will prevent the user from closing the now existing error
1419 * message, simply close the dialog (this is the best we can do here). */
1421 window_destroy(GTK_WIDGET (fs));
1423 gtk_widget_show(GTK_WIDGET (fs));
1428 /* The write succeeded; get rid of the file selection box. */
1429 /* cf_save might already closed our dialog! */
1431 window_destroy(GTK_WIDGET (fs));
1433 /* Save the directory name for future file dialogs. */
1434 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1435 set_last_open_dir(dirname);
1438 /* we have finished saving, do we have pending things to do? */
1439 switch(action_after_save_g) {
1440 case(after_save_no_action):
1442 case(after_save_open_dialog):
1443 file_open_cmd(action_after_save_data_g);
1445 case(after_save_open_recent_file):
1446 menu_open_recent_file_cmd(action_after_save_data_g);
1448 case(after_save_open_dnd_file):
1449 dnd_open_file_cmd(action_after_save_data_g);
1451 case(after_save_merge_dialog):
1452 file_merge_cmd(action_after_save_data_g);
1455 case(after_save_capture_dialog):
1459 case(after_save_close_file):
1462 case(after_save_exit):
1466 g_assert_not_reached();
1469 action_after_save_g = after_save_no_action;
1473 file_save_as_destroy(void)
1476 window_destroy(file_save_as_w);
1480 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1482 /* Note that we no longer have a "Save Capture File As" dialog box. */
1483 file_save_as_w = NULL;
1486 /* Reload a file using the current read and display filters */
1488 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1492 /******************** Color Filters *********************************/
1494 * Keep a static pointer to the current "Color Export" window, if
1495 * any, so that if somebody tries to do "Export"
1496 * while there's already a "Color Export" window up, we just pop
1497 * up the existing one, rather than creating a new one.
1499 static GtkWidget *file_color_import_w;
1501 /* sets the file path to the global color filter file.
1502 WARNING: called by both the import and the export dialog.
1505 color_global_cb(GtkWidget *widget _U_, gpointer data)
1507 GtkWidget *fs_widget = data;
1510 /* decide what file to open (from dfilter code) */
1511 path = get_datafile_path("colorfilters");
1513 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1514 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1516 file_selection_set_current_folder(fs_widget, path);
1518 g_free((gchar *)path);
1521 /* Import color filters */
1523 file_color_import_cmd_cb(GtkWidget *w _U_, gpointer data)
1525 GtkWidget *main_vb, *cfglobal_but;
1526 #if GTK_MAJOR_VERSION < 2
1527 GtkAccelGroup *accel_group;
1529 /* No Apply button, and "OK" just sets our text widget, it doesn't
1530 activate it (i.e., it doesn't cause us to try to open the file). */
1532 if (file_color_import_w != NULL) {
1533 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1534 reactivate_window(file_color_import_w);
1538 file_color_import_w = file_selection_new("Ethereal: Import Color Filters",
1539 FILE_SELECTION_OPEN);
1541 #if GTK_MAJOR_VERSION < 2
1542 /* Accelerator group for the accelerators (or, as they're called in
1543 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
1544 Ctrl+<key> is an accelerator). */
1545 accel_group = gtk_accel_group_new();
1546 gtk_window_add_accel_group(GTK_WINDOW(file_color_import_w), accel_group);
1549 /* Container for each row of widgets */
1550 main_vb = gtk_vbox_new(FALSE, 3);
1551 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1552 file_selection_set_extra_widget(file_color_import_w, main_vb);
1553 gtk_widget_show(main_vb);
1556 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1557 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1558 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_import_w);
1559 gtk_widget_show(cfglobal_but);
1561 SIGNAL_CONNECT(file_color_import_w, "destroy", file_color_import_destroy_cb, NULL);
1563 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1564 OBJECT_SET_DATA(file_color_import_w, ARGUMENT_CL, data);
1566 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1568 file_color_import_ok_cb(file_color_import_w, file_color_import_w);
1570 else window_destroy(file_color_import_w);
1572 /* Connect the ok_button to file_open_ok_cb function and pass along a
1573 pointer to the file selection box widget */
1574 SIGNAL_CONNECT(GTK_FILE_SELECTION(file_color_import_w)->ok_button, "clicked",
1575 file_color_import_ok_cb, file_color_import_w);
1577 OBJECT_SET_DATA(GTK_FILE_SELECTION(file_color_import_w)->ok_button,
1580 window_set_cancel_button(file_color_import_w,
1581 GTK_FILE_SELECTION(file_color_import_w)->cancel_button, window_cancel_button_cb);
1583 SIGNAL_CONNECT(file_color_import_w, "delete_event", window_delete_event_cb, NULL);
1586 gtk_widget_show(file_color_import_w);
1587 window_present(file_color_import_w);
1592 file_color_import_ok_cb(GtkWidget *w, gpointer fs) {
1596 argument = OBJECT_GET_DATA(w, ARGUMENT_CL); /* to be passed back into read_other_filters */
1598 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1599 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1601 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1603 /* Perhaps the user specified a directory instead of a file.
1604 Check whether they did. */
1605 if (test_for_directory(cf_name) == EISDIR) {
1606 /* It's a directory - set the file selection box to display that
1607 directory, don't try to open the directory as a capture file. */
1608 set_last_open_dir(cf_name);
1610 file_selection_set_current_folder(fs, get_last_open_dir());
1614 /* Try to open the capture file. */
1616 if (!read_other_filters(cf_name, argument)) {
1617 /* We couldn't open it; don't dismiss the open dialog box,
1618 just leave it around so that the user can, after they
1619 dismiss the alert box popped up for the open error,
1625 /* We've crossed the Rubicon; get rid of the file selection box. */
1626 window_destroy(GTK_WIDGET (fs));
1628 /* Save the name of the containing directory specified in the path name,
1629 if any; we can write over cf_name, which is a good thing, given that
1630 "get_dirname()" does write over its argument. */
1631 s = get_dirname(cf_name);
1632 set_last_open_dir(s);
1633 gtk_widget_grab_focus(packet_list);
1639 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1641 /* Note that we no longer have a "Open Capture File" dialog box. */
1642 file_color_import_w = NULL;
1645 static GtkWidget *file_color_export_w;
1647 * Set the "Export only marked filters" toggle button as appropriate for
1648 * the current output file type and count of marked filters.
1650 * Called when the "Export" dialog box is created and when the marked
1654 color_set_export_marked_sensitive(GtkWidget * cfmark_cb)
1656 if (file_color_export_w == NULL) {
1657 /* We don't currently have an "Export" dialog box up. */
1661 /* We can request that only the marked filters be saved only if
1662 there *are* marked filters. */
1663 if (color_marked_count() != 0)
1664 gtk_widget_set_sensitive(cfmark_cb, TRUE);
1666 /* Force the "Export only marked filters" toggle to "false", turn
1667 off the flag it controls. */
1668 color_marked = FALSE;
1669 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1670 gtk_widget_set_sensitive(cfmark_cb, FALSE);
1675 color_toggle_marked_cb(GtkWidget *widget, gpointer data _U_)
1677 color_marked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1681 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1683 GtkWidget *main_vb, *cfglobal_but;
1685 if (file_color_export_w != NULL) {
1686 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1687 reactivate_window(file_color_export_w);
1691 /* Default to saving all packets, in the file's current format. */
1692 color_marked = FALSE;
1693 filetype = cfile.cd_t;
1695 file_color_export_w = file_selection_new("Ethereal: Export Color Filters",
1696 FILE_SELECTION_SAVE);
1698 /* Container for each row of widgets */
1699 main_vb = gtk_vbox_new(FALSE, 3);
1700 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
1701 file_selection_set_extra_widget(file_color_export_w, main_vb);
1702 gtk_widget_show(main_vb);
1704 cfmark_cb = gtk_check_button_new_with_label("Export only marked filters");
1705 gtk_container_add(GTK_CONTAINER(main_vb), cfmark_cb);
1706 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfmark_cb), FALSE);
1707 SIGNAL_CONNECT(cfmark_cb, "toggled", color_toggle_marked_cb, NULL);
1708 gtk_widget_show(cfmark_cb);
1709 color_set_export_marked_sensitive(cfmark_cb);
1711 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1712 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1713 SIGNAL_CONNECT(cfglobal_but, "clicked", color_global_cb, file_color_export_w);
1714 gtk_widget_show(cfglobal_but);
1716 SIGNAL_CONNECT(file_color_export_w, "destroy", file_color_export_destroy_cb, NULL);
1718 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1719 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1721 file_color_export_ok_cb(file_color_export_w, file_color_export_w);
1723 else window_destroy(file_color_export_w);
1725 /* Connect the ok_button to file_export_ok_cb function and pass along a
1726 pointer to the file selection box widget */
1727 SIGNAL_CONNECT(GTK_FILE_SELECTION (file_color_export_w)->ok_button, "clicked",
1728 file_color_export_ok_cb, file_color_export_w);
1730 window_set_cancel_button(file_color_export_w,
1731 GTK_FILE_SELECTION(file_color_export_w)->cancel_button, window_cancel_button_cb);
1733 SIGNAL_CONNECT(file_color_export_w, "delete_event", window_delete_event_cb, NULL);
1736 gtk_file_selection_set_filename(GTK_FILE_SELECTION(file_color_export_w), "");
1738 gtk_widget_show(file_color_export_w);
1739 window_present(file_color_export_w);
1744 file_color_export_ok_cb(GtkWidget *w _U_, gpointer fs) {
1748 #if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 4) || GTK_MAJOR_VERSION > 2
1749 cf_name = g_strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs)));
1751 cf_name = g_strdup(gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
1754 /* Perhaps the user specified a directory instead of a file.
1755 Check whether they did. */
1756 if (test_for_directory(cf_name) == EISDIR) {
1757 /* It's a directory - set the file selection box to display that
1758 directory, and leave the selection box displayed. */
1759 set_last_open_dir(cf_name);
1761 file_selection_set_current_folder(fs, get_last_open_dir());
1765 /* Write out the filters (all, or only the ones that are currently
1766 displayed or marked) to the file with the specified name. */
1768 if (!write_other_filters(cf_name, color_marked))
1770 /* The write failed; don't dismiss the open dialog box,
1771 just leave it around so that the user can, after they
1772 dismiss the alert box popped up for the error, try again. */
1778 /* The write succeeded; get rid of the file selection box. */
1779 window_destroy(GTK_WIDGET (fs));
1781 /* Save the directory name for future file dialogs. */
1782 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1783 set_last_open_dir(dirname);
1788 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1790 file_color_export_w = NULL;