2 * Dialog boxes for handling capture files
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
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.
37 #include "packet-range.h"
38 #include <epan/filesystem.h>
39 #include <epan/addr_resolv.h>
40 #include <epan/prefs.h>
42 #include "../globals.h"
43 #include "../alert_box.h"
44 #include "../simple_dialog.h"
46 #include "../ui_util.h"
47 #include "../color_filters.h"
50 #include <wsutil/file_util.h>
52 #include "gtk/gtkglobals.h"
54 #include "gtk/filter_dlg.h"
55 #include "gtk/gui_utils.h"
56 #include "gtk/dlg_utils.h"
57 #include "gtk/file_dlg.h"
58 #include "gtk/capture_file_dlg.h"
59 #include "gtk/drag_and_drop.h"
61 #include "gtk/menus.h"
62 #include "gtk/recent.h"
63 #include "gtk/color_dlg.h"
64 #ifdef NEW_PACKET_LIST
65 #include "gtk/new_packet_list.h"
68 #include "gtk/capture_dlg.h"
70 #include "gtk/stock_icons.h"
71 #include "gtk/range_utils.h"
72 #include "gtk/filter_autocomplete.h"
75 #include <gdk/gdkwin32.h>
77 #include "gtk/file_dlg_win32.h"
81 static void file_open_ok_cb(GtkWidget *w, gpointer fs);
82 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
83 static void file_merge_ok_cb(GtkWidget *w, gpointer fs);
84 static void file_merge_destroy_cb(GtkWidget *win, gpointer user_data);
85 static void select_file_type_cb(GtkWidget *w, gpointer data);
86 static void file_save_as_ok_cb(GtkWidget *w, gpointer fs);
87 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
88 static void file_color_import_ok_cb(GtkWidget *w, gpointer filter_list);
89 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
90 static void file_color_export_ok_cb(GtkWidget *w, gpointer filter_list);
91 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
92 static void set_file_type_list(GtkWidget *option_menu);
94 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
95 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
96 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
98 #define E_MERGE_PREPEND_KEY "merge_dlg_prepend_key"
99 #define E_MERGE_CHRONO_KEY "merge_dlg_chrono_key"
100 #define E_MERGE_APPEND_KEY "merge_dlg_append_key"
103 #define PREVIEW_TABLE_KEY "preview_table_key"
104 #define PREVIEW_FILENAME_KEY "preview_filename_key"
105 #define PREVIEW_FORMAT_KEY "preview_format_key"
106 #define PREVIEW_SIZE_KEY "preview_size_key"
107 #define PREVIEW_ELAPSED_KEY "preview_elapsed_key"
108 #define PREVIEW_PACKETS_KEY "preview_packets_key"
109 #define PREVIEW_FIRST_KEY "preview_first_key"
113 * Keep a static pointer to the current "Save Capture File As" window, if
114 * any, so that if somebody tries to do "File:Save" or "File:Save As"
115 * while there's already a "Save Capture File As" window up, we just pop
116 * up the existing one, rather than creating a new one.
118 static GtkWidget *file_save_as_w;
120 /* XXX - can we make these not be static? */
121 static packet_range_t range;
122 static gboolean color_selected;
124 static GtkWidget *ft_om;
125 static GtkWidget *range_tb;
127 #define PREVIEW_STR_MAX 200
130 /* set a new filename for the preview widget */
132 preview_set_filename(GtkWidget *prev, const gchar *cf_name)
138 gchar string_buff[PREVIEW_STR_MAX];
142 /* init preview labels */
143 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FILENAME_KEY);
144 gtk_label_set_text(GTK_LABEL(label), "-");
145 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
146 gtk_label_set_text(GTK_LABEL(label), "-");
147 label = g_object_get_data(G_OBJECT(prev), PREVIEW_SIZE_KEY);
148 gtk_label_set_text(GTK_LABEL(label), "-");
149 label = g_object_get_data(G_OBJECT(prev), PREVIEW_ELAPSED_KEY);
150 gtk_label_set_text(GTK_LABEL(label), "-");
151 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
152 gtk_label_set_text(GTK_LABEL(label), "-");
153 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FIRST_KEY);
154 gtk_label_set_text(GTK_LABEL(label), "-");
160 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FILENAME_KEY);
161 gtk_label_set_text(GTK_LABEL(label), get_basename(cf_name));
163 if (test_for_directory(cf_name) == EISDIR) {
164 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
165 gtk_label_set_text(GTK_LABEL(label), "directory");
169 wth = wtap_open_offline(cf_name, &err, &err_info, TRUE);
171 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
172 if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
173 gtk_label_set_text(GTK_LABEL(label), "unknown file format");
175 gtk_label_set_text(GTK_LABEL(label), "error opening file");
180 /* Find the size of the file. */
181 filesize = wtap_file_size(wth, &err);
182 if (filesize == -1) {
183 gtk_label_set_text(GTK_LABEL(label), "error getting file size");
187 g_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_MODIFIER "d bytes", filesize);
188 label = g_object_get_data(G_OBJECT(prev), PREVIEW_SIZE_KEY);
189 gtk_label_set_text(GTK_LABEL(label), string_buff);
192 g_strlcpy(string_buff, wtap_file_type_string(wtap_file_type(wth)), PREVIEW_STR_MAX);
193 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
194 gtk_label_set_text(GTK_LABEL(label), string_buff);
200 /* do a preview run on the currently selected capture file */
202 preview_do(GtkWidget *prev, wtap *wth)
205 unsigned int elapsed_time;
211 const struct wtap_pkthdr *phdr;
212 double start_time = 0; /* seconds, with nsec resolution */
213 double stop_time = 0; /* seconds, with nsec resolution */
215 unsigned int packets = 0;
216 gboolean is_breaked = FALSE;
217 gchar string_buff[PREVIEW_STR_MAX];
223 while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
224 phdr = wtap_phdr(wth);
225 cur_time = wtap_nstime_to_sec(&phdr->ts);
227 start_time = cur_time;
228 stop_time = cur_time;
230 if (cur_time < start_time) {
231 start_time = cur_time;
233 if (cur_time > stop_time){
234 stop_time = cur_time;
238 if(packets%1000 == 0) {
239 /* do we have a timeout? */
241 if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
249 g_snprintf(string_buff, PREVIEW_STR_MAX, "error after reading %u packets", packets);
250 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
251 gtk_label_set_text(GTK_LABEL(label), string_buff);
258 g_snprintf(string_buff, PREVIEW_STR_MAX, "more than %u packets (preview timeout)", packets);
260 g_snprintf(string_buff, PREVIEW_STR_MAX, "%u", packets);
262 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
263 gtk_label_set_text(GTK_LABEL(label), string_buff);
266 ti_time = (long)start_time;
267 ti_tm = localtime( &ti_time );
269 g_snprintf(string_buff, PREVIEW_STR_MAX,
270 "%04d-%02d-%02d %02d:%02d:%02d",
271 ti_tm->tm_year + 1900,
278 g_snprintf(string_buff, PREVIEW_STR_MAX, "?");
280 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FIRST_KEY);
281 gtk_label_set_text(GTK_LABEL(label), string_buff);
284 elapsed_time = (unsigned int)(stop_time-start_time);
285 if(elapsed_time/86400) {
286 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u days %02u:%02u:%02u",
287 elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
289 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u:%02u:%02u",
290 elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
293 g_snprintf(string_buff, PREVIEW_STR_MAX, "unknown");
295 label = g_object_get_data(G_OBJECT(prev), PREVIEW_ELAPSED_KEY);
296 gtk_label_set_text(GTK_LABEL(label), string_buff);
302 /* as the dialog layout will look very ugly when using the file chooser preview mechanism,
303 simply use the same layout as in GTK2.0 */
305 update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
307 GtkWidget *prev = GTK_WIDGET (data);
309 gboolean have_preview;
311 cf_name = gtk_file_chooser_get_preview_filename (file_chooser);
313 have_preview = preview_set_filename(prev, cf_name);
318 gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
323 /* the filename text entry changed */
325 file_open_entry_changed(GtkWidget *w _U_, gpointer file_sel)
327 GtkWidget *prev = g_object_get_data(G_OBJECT(file_sel), PREVIEW_TABLE_KEY);
329 gboolean have_preview;
332 /* get the filename */
333 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_sel));
335 /* set the filename to the preview */
336 wth = preview_set_filename(prev, cf_name);
337 have_preview = (wth != NULL);
341 /* make the preview widget sensitive */
342 gtk_widget_set_sensitive(prev, have_preview);
344 /* make the open/save/... dialog button sensitive */
346 gtk_dialog_set_response_sensitive(file_sel, GTK_RESPONSE_ACCEPT, have_preview);
348 /* do the actual preview */
350 preview_do(prev, wth);
354 /* copied from summary_dlg.c */
356 add_string_to_table_sensitive(GtkWidget *list, guint *row, const gchar *title, const gchar *value, gboolean sensitive)
361 if(strlen(value) != 0) {
362 indent = g_strdup_printf(" %s", title);
364 indent = g_strdup(title);
366 label = gtk_label_new(indent);
368 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
369 gtk_widget_set_sensitive(label, sensitive);
370 gtk_table_attach_defaults(GTK_TABLE(list), label, 0, 1, *row, *row+1);
372 label = gtk_label_new(value);
373 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
374 gtk_widget_set_sensitive(label, sensitive);
375 gtk_table_attach_defaults(GTK_TABLE(list), label, 1, 2, *row, *row+1);
383 add_string_to_table(GtkWidget *list, guint *row, const gchar *title, const gchar *value)
385 return add_string_to_table_sensitive(list, row, title, value, TRUE);
393 GtkWidget *table, *label;
396 table = gtk_table_new(1, 2, FALSE);
397 gtk_table_set_col_spacings(GTK_TABLE(table), 6);
398 gtk_table_set_row_spacings(GTK_TABLE(table), 3);
401 label = add_string_to_table(table, &row, "Filename:", "-");
402 gtk_widget_set_size_request(label, DEF_WIDTH/3, -1);
403 g_object_set_data(G_OBJECT(table), PREVIEW_FILENAME_KEY, label);
404 label = add_string_to_table(table, &row, "Format:", "-");
405 g_object_set_data(G_OBJECT(table), PREVIEW_FORMAT_KEY, label);
406 label = add_string_to_table(table, &row, "Size:", "-");
407 g_object_set_data(G_OBJECT(table), PREVIEW_SIZE_KEY, label);
408 label = add_string_to_table(table, &row, "Packets:", "-");
409 g_object_set_data(G_OBJECT(table), PREVIEW_PACKETS_KEY, label);
410 label = add_string_to_table(table, &row, "First Packet:", "-");
411 g_object_set_data(G_OBJECT(table), PREVIEW_FIRST_KEY, label);
412 label = add_string_to_table(table, &row, "Elapsed time:", "-");
413 g_object_set_data(G_OBJECT(table), PREVIEW_ELAPSED_KEY, label);
419 * Keep a static pointer to the current "Open Capture File" window, if
420 * any, so that if somebody tries to do "File:Open" while there's already
421 * an "Open Capture File" window up, we just pop up the existing one,
422 * rather than creating a new one.
424 static GtkWidget *file_open_w;
428 file_open_cmd(GtkWidget *w)
431 win32_open_file(GDK_WINDOW_HWND(top_level->window));
433 GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te,
434 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, *prev;
435 GtkTooltips *tooltips = gtk_tooltips_new();
436 /* No Apply button, and "OK" just sets our text widget, it doesn't
437 activate it (i.e., it doesn't cause us to try to open the file). */
438 static construct_args_t args = {
439 "Wireshark: Read Filter",
445 if (file_open_w != NULL) {
446 /* There's already an "Open Capture File" dialog box; reactivate it. */
447 reactivate_window(file_open_w);
451 file_open_w = file_selection_new("Wireshark: Open Capture File",
452 FILE_SELECTION_OPEN);
453 /* it's annoying, that the file chooser dialog is already shown here,
454 so we cannot use the correct gtk_window_set_default_size() to resize it */
455 gtk_widget_set_size_request(file_open_w, DEF_WIDTH, DEF_HEIGHT);
457 switch (prefs.gui_fileopen_style) {
459 case FO_STYLE_LAST_OPENED:
460 /* The user has specified that we should start out in the last directory
461 we looked in. If we've already opened a file, use its containing
462 directory, if we could determine it, as the directory, otherwise
463 use the "last opened" directory saved in the preferences file if
465 /* This is now the default behaviour in file_selection_new() */
468 case FO_STYLE_SPECIFIED:
469 /* The user has specified that we should always start out in a
470 specified directory; if they've specified that directory,
471 start out by showing the files in that dir. */
472 if (prefs.gui_fileopen_dir[0] != '\0')
473 file_selection_set_current_folder(file_open_w, prefs.gui_fileopen_dir);
478 main_hb = gtk_hbox_new(FALSE, 3);
479 file_selection_set_extra_widget(file_open_w, main_hb);
480 gtk_widget_show(main_hb);
482 /* Container for each row of widgets */
483 main_vb = gtk_vbox_new(FALSE, 3);
484 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
485 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
486 gtk_widget_show(main_vb);
489 filter_hbox = gtk_hbox_new(FALSE, 1);
490 gtk_container_set_border_width(GTK_CONTAINER(filter_hbox), 0);
491 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
492 gtk_widget_show(filter_hbox);
494 filter_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
495 g_signal_connect(filter_bt, "clicked",
496 G_CALLBACK(display_filter_construct_cb), &args);
497 g_signal_connect(filter_bt, "destroy",
498 G_CALLBACK(filter_button_destroy_cb), NULL);
499 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
500 gtk_widget_show(filter_bt);
501 gtk_tooltips_set_tip(tooltips, filter_bt,
502 "Open the \"Display Filter\" dialog, to edit/apply filters", NULL);
504 filter_te = gtk_entry_new();
505 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
506 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
507 g_signal_connect(filter_te, "changed",
508 G_CALLBACK(filter_te_syntax_check_cb), NULL);
509 g_object_set_data(G_OBJECT(filter_hbox), E_FILT_AUTOCOMP_PTR_KEY, NULL);
510 g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
511 g_signal_connect(file_open_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
512 colorize_filter_te_as_empty(filter_te);
513 gtk_widget_show(filter_te);
514 gtk_tooltips_set_tip(tooltips, filter_te, "Enter a display filter.", NULL);
516 g_object_set_data(G_OBJECT(file_open_w), E_RFILTER_TE_KEY, filter_te);
518 /* resolve buttons */
519 m_resolv_cb = gtk_check_button_new_with_mnemonic("Enable _MAC name resolution");
520 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
521 g_resolv_flags & RESOLV_MAC);
522 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
523 g_object_set_data(G_OBJECT(file_open_w),
524 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
525 gtk_widget_show(m_resolv_cb);
527 n_resolv_cb = gtk_check_button_new_with_mnemonic("Enable _network name resolution");
528 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
529 g_resolv_flags & RESOLV_NETWORK);
530 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
531 gtk_widget_show(n_resolv_cb);
532 g_object_set_data(G_OBJECT(file_open_w), E_FILE_N_RESOLVE_KEY, n_resolv_cb);
533 t_resolv_cb = gtk_check_button_new_with_mnemonic("Enable _transport name resolution");
534 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
535 g_resolv_flags & RESOLV_TRANSPORT);
536 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
537 gtk_widget_show(t_resolv_cb);
538 g_object_set_data(G_OBJECT(file_open_w), E_FILE_T_RESOLVE_KEY, t_resolv_cb);
540 g_signal_connect(file_open_w, "destroy",
541 G_CALLBACK(file_open_destroy_cb), NULL);
544 prev = preview_new();
545 g_object_set_data(G_OBJECT(file_open_w), PREVIEW_TABLE_KEY, prev);
546 gtk_widget_show_all(prev);
547 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
549 g_signal_connect(GTK_FILE_CHOOSER(file_open_w), "selection-changed",
550 G_CALLBACK(file_open_entry_changed), file_open_w);
551 file_open_entry_changed(file_open_w, file_open_w);
553 g_object_set_data(G_OBJECT(file_open_w), E_DFILTER_TE_KEY,
554 g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
555 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
557 file_open_ok_cb(file_open_w, file_open_w);
559 else window_destroy(file_open_w);
563 static void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
567 /* save file first */
568 file_save_as_cmd(after_save_open_dialog, data);
570 case(ESD_BTN_DONT_SAVE):
574 case(ESD_BTN_CANCEL):
577 g_assert_not_reached();
582 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
585 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
586 /* user didn't save his current file, ask him */
587 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
588 "%sSave capture file before opening a new one?%s\n\n"
589 "If you open a new capture file without saving, your capture data will be discarded.",
590 simple_dialog_primary_start(), simple_dialog_primary_end());
591 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
593 /* unchanged file, just open a new one */
594 file_open_cmd(widget);
598 /* user pressed "open" button */
600 file_open_ok_cb(GtkWidget *w, gpointer fs) {
602 const gchar *rfilter;
603 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
604 dfilter_t *rfcode = NULL;
607 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
608 filter_te = g_object_get_data(G_OBJECT(w), E_RFILTER_TE_KEY);
609 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
610 if (!dfilter_compile(rfilter, &rfcode)) {
611 bad_dfilter_alert_box(rfilter);
616 /* Perhaps the user specified a directory instead of a file.
617 Check whether they did. */
618 if (test_for_directory(cf_name) == EISDIR) {
619 /* It's a directory - set the file selection box to display that
620 directory, don't try to open the directory as a capture file. */
621 set_last_open_dir(cf_name);
623 file_selection_set_current_folder(fs, get_last_open_dir());
627 /* Try to open the capture file. */
628 if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) {
629 /* We couldn't open it; don't dismiss the open dialog box,
630 just leave it around so that the user can, after they
631 dismiss the alert box popped up for the open error,
634 dfilter_free(rfcode);
637 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
638 * as this will prevent the user from closing the now existing error
639 * message, simply close the dialog (this is the best we can do here). */
641 window_destroy(file_open_w);
646 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
647 it closed the previous capture file, and thus destroyed any
648 previous read filter attached to "cf"). */
649 cfile.rfcode = rfcode;
651 /* Set the global resolving variable */
652 g_resolv_flags = prefs.name_resolve;
653 m_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_M_RESOLVE_KEY);
654 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)))
655 g_resolv_flags |= RESOLV_MAC;
657 g_resolv_flags &= ~RESOLV_MAC;
658 n_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_N_RESOLVE_KEY);
659 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)))
660 g_resolv_flags |= RESOLV_NETWORK;
662 g_resolv_flags &= ~RESOLV_NETWORK;
663 t_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_T_RESOLVE_KEY);
664 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)))
665 g_resolv_flags |= RESOLV_TRANSPORT;
667 g_resolv_flags &= ~RESOLV_TRANSPORT;
669 /* We've crossed the Rubicon; get rid of the file selection box. */
670 window_destroy(GTK_WIDGET (fs));
672 switch (cf_read(&cfile)) {
676 /* Just because we got an error, that doesn't mean we were unable
677 to read any of the file; we handle what we could get from the
681 case CF_READ_ABORTED:
682 /* The user bailed out of re-reading the capture file; the
683 capture file has been closed - just free the capture file name
684 string and return (without changing the last containing
690 /* Save the name of the containing directory specified in the path name,
691 if any; we can write over cf_name, which is a good thing, given that
692 "get_dirname()" does write over its argument. */
693 s = get_dirname(cf_name);
694 set_last_open_dir(s);
695 #ifndef NEW_PACKET_LIST
696 gtk_widget_grab_focus(packet_list);
703 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
705 /* Note that we no longer have a "Open Capture File" dialog box. */
710 * Keep a static pointer to the current "Merge Capture File" window, if
711 * any, so that if somebody tries to do "File:Merge" while there's already
712 * an "Merge Capture File" window up, we just pop up the existing one,
713 * rather than creating a new one.
715 static GtkWidget *file_merge_w;
717 /* Merge existing with another file */
719 file_merge_cmd(GtkWidget *w)
722 win32_merge_file(GDK_WINDOW_HWND(top_level->window));
723 #ifdef NEW_PACKET_LIST
724 new_packet_list_freeze();
725 new_packet_list_thaw();
727 packet_list_freeze();
729 #endif /* NEW_PACKET_LIST */
731 GtkWidget *main_hb, *main_vb, *ft_hb, *ft_lb, *filter_hbox,
732 *filter_bt, *filter_te, *prepend_rb, *chrono_rb,
734 GtkTooltips *tooltips = gtk_tooltips_new();
735 /* No Apply button, and "OK" just sets our text widget, it doesn't
736 activate it (i.e., it doesn't cause us to try to open the file). */
737 static construct_args_t args = {
738 "Wireshark: Read Filter",
744 if (file_merge_w != NULL) {
745 /* There's already an "Merge Capture File" dialog box; reactivate it. */
746 reactivate_window(file_merge_w);
750 /* Default to saving all packets, in the file's current format. */
751 filetype = cfile.cd_t;
753 file_merge_w = file_selection_new("Wireshark: Merge with Capture File",
754 FILE_SELECTION_OPEN);
755 /* it's annoying, that the file chooser dialog is already shown here,
756 so we cannot use the correct gtk_window_set_default_size() to resize it */
757 gtk_widget_set_size_request(file_merge_w, DEF_WIDTH, DEF_HEIGHT);
759 switch (prefs.gui_fileopen_style) {
761 case FO_STYLE_LAST_OPENED:
762 /* The user has specified that we should start out in the last directory
763 we looked in. If we've already opened a file, use its containing
764 directory, if we could determine it, as the directory, otherwise
765 use the "last opened" directory saved in the preferences file if
767 /* This is now the default behaviour in file_selection_new() */
770 case FO_STYLE_SPECIFIED:
771 /* The user has specified that we should always start out in a
772 specified directory; if they've specified that directory,
773 start out by showing the files in that dir. */
774 if (prefs.gui_fileopen_dir[0] != '\0')
775 file_selection_set_current_folder(file_merge_w, prefs.gui_fileopen_dir);
779 main_hb = gtk_hbox_new(FALSE, 3);
780 file_selection_set_extra_widget(file_merge_w, main_hb);
781 gtk_widget_show(main_hb);
783 /* Container for each row of widgets */
784 main_vb = gtk_vbox_new(FALSE, 3);
785 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
786 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
787 gtk_widget_show(main_vb);
791 ft_hb = gtk_hbox_new(FALSE, 3);
792 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
793 gtk_widget_show(ft_hb);
795 ft_lb = gtk_label_new("Merged output file type:");
796 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
797 gtk_widget_show(ft_lb);
799 ft_om = gtk_option_menu_new();
801 /* Generate the list of file types we can save. */
802 set_file_type_list(ft_om);
803 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
804 gtk_widget_show(ft_om);
806 filter_hbox = gtk_hbox_new(FALSE, 1);
807 gtk_container_set_border_width(GTK_CONTAINER(filter_hbox), 0);
808 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
809 gtk_widget_show(filter_hbox);
811 filter_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
812 g_signal_connect(filter_bt, "clicked",
813 G_CALLBACK(display_filter_construct_cb), &args);
814 g_signal_connect(filter_bt, "destroy",
815 G_CALLBACK(filter_button_destroy_cb), NULL);
816 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
817 gtk_widget_show(filter_bt);
818 gtk_tooltips_set_tip(tooltips, filter_bt,
819 "Open the \"Display Filter\" dialog, to edit/apply filters", NULL);
821 filter_te = gtk_entry_new();
822 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
823 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
824 g_signal_connect(filter_te, "changed",
825 G_CALLBACK(filter_te_syntax_check_cb), NULL);
826 g_object_set_data(G_OBJECT(filter_hbox), E_FILT_AUTOCOMP_PTR_KEY, NULL);
827 g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
828 g_signal_connect(file_merge_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
829 colorize_filter_te_as_empty(filter_te);
830 gtk_widget_show(filter_te);
831 gtk_tooltips_set_tip(tooltips, filter_te, "Enter a display filter.", NULL);
833 g_object_set_data(G_OBJECT(file_merge_w), E_RFILTER_TE_KEY, filter_te);
835 prepend_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL,
836 "Prepend packets to existing file");
837 gtk_tooltips_set_tip(tooltips, prepend_rb,
838 "The resulting file contains the packets from the selected, followed by the packets from the currently loaded file,"
839 " the packet timestamps will be ignored.", NULL);
840 gtk_box_pack_start(GTK_BOX(main_vb), prepend_rb, FALSE, FALSE, 0);
841 g_object_set_data(G_OBJECT(file_merge_w),
842 E_MERGE_PREPEND_KEY, prepend_rb);
843 gtk_widget_show(prepend_rb);
845 chrono_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(prepend_rb), "Merge packets chronologically");
846 gtk_tooltips_set_tip(tooltips, chrono_rb,
847 "The resulting file contains all the packets from the currently loaded and the selected file,"
848 " sorted by the packet timestamps.", NULL);
849 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chrono_rb), TRUE);
850 gtk_box_pack_start(GTK_BOX(main_vb), chrono_rb, FALSE, FALSE, 0);
851 gtk_widget_show(chrono_rb);
852 g_object_set_data(G_OBJECT(file_merge_w), E_MERGE_CHRONO_KEY, chrono_rb);
854 append_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(prepend_rb), "Append packets to existing file");
855 gtk_tooltips_set_tip(tooltips, append_rb,
856 "The resulting file contains the packets from the currently loaded, followed by the packets from the selected file,"
857 " the packet timestamps will be ignored.", NULL);
858 gtk_box_pack_start(GTK_BOX(main_vb), append_rb, FALSE, FALSE, 0);
859 gtk_widget_show(append_rb);
860 g_object_set_data(G_OBJECT(file_merge_w), E_MERGE_APPEND_KEY, append_rb);
862 g_signal_connect(file_merge_w, "destroy",
863 G_CALLBACK(file_merge_destroy_cb), NULL);
866 prev = preview_new();
867 g_object_set_data(G_OBJECT(file_merge_w), PREVIEW_TABLE_KEY, prev);
868 gtk_widget_show_all(prev);
869 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
871 g_signal_connect(GTK_FILE_CHOOSER(file_merge_w), "selection-changed",
872 G_CALLBACK(file_open_entry_changed), file_merge_w);
873 file_open_entry_changed(file_merge_w, file_merge_w);
875 g_object_set_data(G_OBJECT(file_merge_w), E_DFILTER_TE_KEY,
876 g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
877 if (gtk_dialog_run(GTK_DIALOG(file_merge_w)) == GTK_RESPONSE_ACCEPT)
879 file_merge_ok_cb(file_merge_w, file_merge_w);
881 else window_destroy(file_merge_w);
885 static void file_merge_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
889 /* save file first */
890 file_save_as_cmd(after_save_merge_dialog, data);
892 case(ESD_BTN_CANCEL):
895 g_assert_not_reached();
900 file_merge_cmd_cb(GtkWidget *widget, gpointer data _U_) {
903 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
904 /* user didn't saved his current file, ask him */
905 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
906 "%sSave the capture file before merging to another one?%s\n\n"
907 "A temporary capture file can't be merged.",
908 simple_dialog_primary_start(), simple_dialog_primary_end());
909 simple_dialog_set_cb(dialog, file_merge_answered_cb, widget);
911 /* unchanged file, just start to merge */
912 file_merge_cmd(widget);
918 file_merge_ok_cb(GtkWidget *w, gpointer fs) {
920 const gchar *rfilter;
921 GtkWidget *filter_te, *rb;
922 dfilter_t *rfcode = NULL;
924 cf_status_t merge_status;
925 char *in_filenames[2];
928 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
929 filter_te = g_object_get_data(G_OBJECT(w), E_RFILTER_TE_KEY);
930 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
931 if (!dfilter_compile(rfilter, &rfcode)) {
932 bad_dfilter_alert_box(rfilter);
937 /* Perhaps the user specified a directory instead of a file.
938 Check whether they did. */
939 if (test_for_directory(cf_name) == EISDIR) {
940 /* It's a directory - set the file selection box to display that
941 directory, don't try to open the directory as a capture file. */
942 set_last_open_dir(cf_name);
944 file_selection_set_current_folder(fs, get_last_open_dir());
948 /* merge or append the two files */
949 rb = g_object_get_data(G_OBJECT(w), E_MERGE_CHRONO_KEY);
951 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
952 /* chronological order */
953 in_filenames[0] = cfile.filename;
954 in_filenames[1] = cf_name;
955 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, FALSE);
957 rb = g_object_get_data(G_OBJECT(w), E_MERGE_PREPEND_KEY);
958 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
960 in_filenames[0] = cf_name;
961 in_filenames[1] = cfile.filename;
962 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype,
966 in_filenames[0] = cfile.filename;
967 in_filenames[1] = cf_name;
968 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype,
975 if (merge_status != CF_OK) {
977 dfilter_free(rfcode);
984 /* We've crossed the Rubicon; get rid of the file selection box. */
985 window_destroy(GTK_WIDGET (fs));
987 /* Try to open the merged capture file. */
988 if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
989 /* We couldn't open it; don't dismiss the open dialog box,
990 just leave it around so that the user can, after they
991 dismiss the alert box popped up for the open error,
994 dfilter_free(rfcode);
996 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
997 * as this will prevent the user from closing the now existing error
998 * message, simply close the dialog (this is the best we can do here). */
1000 window_destroy(file_open_w);
1005 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
1006 it closed the previous capture file, and thus destroyed any
1007 previous read filter attached to "cf"). */
1008 cfile.rfcode = rfcode;
1010 switch (cf_read(&cfile)) {
1014 /* Just because we got an error, that doesn't mean we were unable
1015 to read any of the file; we handle what we could get from the
1019 case CF_READ_ABORTED:
1020 /* The user bailed out of re-reading the capture file; the
1021 capture file has been closed - just free the capture file name
1022 string and return (without changing the last containing
1027 /* Save the name of the containing directory specified in the path name,
1028 if any; we can write over cf_merged_name, which is a good thing, given that
1029 "get_dirname()" does write over its argument. */
1030 s = get_dirname(tmpname);
1031 set_last_open_dir(s);
1032 #ifndef NEW_PACKET_LIST
1033 gtk_widget_grab_focus(packet_list);
1038 file_merge_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1040 /* Note that we no longer have a "Merge Capture File" dialog box. */
1041 file_merge_w = NULL;
1045 static void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1049 /* save file first */
1050 file_save_as_cmd(after_save_close_file, NULL);
1052 case(ESD_BTN_DONT_SAVE):
1055 case(ESD_BTN_CANCEL):
1058 g_assert_not_reached();
1064 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
1067 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1068 /* user didn't saved his current file, ask him */
1069 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1070 "%sSave capture file before closing it?%s\n\n"
1071 "If you close without saving, your capture data will be discarded.",
1072 simple_dialog_primary_start(), simple_dialog_primary_end());
1074 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
1076 /* unchanged file, just close it */
1082 file_save_cmd_cb(GtkWidget *w, gpointer data) {
1083 /* If the file's already been saved, do nothing. */
1084 if (cfile.user_saved)
1087 /* Do a "Save As". */
1088 file_save_as_cmd_cb(w, data);
1092 can_save_with_wiretap(int ft)
1094 /* To save a file with Wiretap, Wiretap has to handle that format,
1095 and its code to handle that format must be able to write a file
1096 with this file's encapsulation type. */
1097 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
1101 /* Generate a list of the file types we can save this file as, by
1102 checking what Wiretap supports. */
1104 set_file_type_list(GtkWidget *option_menu)
1106 GtkWidget *ft_menu, *ft_menu_item;
1109 gint item_to_select;
1111 /* Default to the first supported file type, if the file's current
1112 type isn't supported. */
1113 item_to_select = -1;
1115 ft_menu = gtk_menu_new();
1117 /* Check all file types. */
1119 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1120 if (can_save_with_wiretap(ft)) {
1121 /* OK, we can write it out in this type. */
1122 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
1123 if (ft == filetype) {
1124 /* Default to the same format as the file, if it's supported. */
1125 item_to_select = index;
1127 g_signal_connect(ft_menu_item, "activate", G_CALLBACK(select_file_type_cb),
1128 GINT_TO_POINTER(ft));
1129 gtk_menu_shell_append(GTK_MENU_SHELL(ft_menu), ft_menu_item);
1130 gtk_widget_show(ft_menu_item);
1135 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
1136 if (item_to_select >= 0) {
1137 /* Select the current File format in the menu */
1138 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
1139 select_file_type_cb(NULL, GINT_TO_POINTER(filetype));
1143 * Manually call the signal handler to activate the first menu item
1144 * since gtk_option_menu_set_history() doesn't do it for us. The first two
1145 * entries in the wiretap file types are placeholders so we start at #2, which
1146 * is the normal libpcap format.
1148 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
1149 select_file_type_cb(NULL, GINT_TO_POINTER(WTAP_FILE_PCAP));
1154 select_file_type_cb(GtkWidget *w _U_, gpointer data)
1156 int new_filetype = GPOINTER_TO_INT(data);
1157 GtkWidget *compressed_cb;
1159 if (filetype != new_filetype) {
1160 filetype = new_filetype;
1161 compressed_cb = g_object_get_data(G_OBJECT(file_save_as_w), "compressed");
1163 gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(new_filetype));
1169 * Update various dynamic parts of the range controls; called from outside
1170 * the file dialog code whenever the packet counts change.
1173 file_save_update_dynamics(void)
1175 if (file_save_as_w == NULL) {
1176 /* We don't currently have a "Save As..." dialog box up. */
1180 range_update_dynamics(range_tb);
1184 action_after_save_e action_after_save_g;
1185 gpointer action_after_save_data_g;
1189 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
1192 win32_save_as_file(GDK_WINDOW_HWND(top_level->window), action_after_save, action_after_save_data);
1194 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *compressed_cb;
1196 if (file_save_as_w != NULL) {
1197 /* There's already an "Save Capture File As" dialog box; reactivate it. */
1198 reactivate_window(file_save_as_w);
1202 /* Default to saving all packets, in the file's current format. */
1203 filetype = cfile.cd_t;
1205 /* init the packet range */
1206 packet_range_init(&range);
1208 /* build the file selection */
1209 file_save_as_w = file_selection_new ("Wireshark: Save Capture File As",
1210 FILE_SELECTION_SAVE);
1212 /* as the dialog might already be gone, when using this values, we cannot
1213 * set data to the dialog object, but keep global values */
1214 action_after_save_g = action_after_save;
1215 action_after_save_data_g = action_after_save_data;
1217 /* Container for each row of widgets */
1219 main_vb = gtk_vbox_new(FALSE, 5);
1220 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1221 file_selection_set_extra_widget(file_save_as_w, main_vb);
1222 gtk_widget_show(main_vb);
1224 /*** Packet Range frame ***/
1225 range_fr = gtk_frame_new("Packet Range");
1226 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
1227 gtk_widget_show(range_fr);
1230 range_tb = range_new(&range);
1231 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
1232 gtk_widget_show(range_tb);
1235 ft_hb = gtk_hbox_new(FALSE, 3);
1236 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1237 gtk_widget_show(ft_hb);
1239 ft_lb = gtk_label_new("File type:");
1240 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1241 gtk_widget_show(ft_lb);
1243 ft_om = gtk_option_menu_new();
1245 /* Generate the list of file types we can save. */
1246 set_file_type_list(ft_om);
1247 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1248 gtk_widget_show(ft_om);
1250 /* dynamic values in the range frame */
1251 range_update_dynamics(range_tb);
1254 compressed_cb = gtk_check_button_new_with_label("Compress with gzip");
1255 gtk_container_add(GTK_CONTAINER(ft_hb), compressed_cb);
1256 /* XXX - disable output compression for now, as this doesn't work with the
1257 * current optimization to simply copy a capture file if it's using the same
1258 * encapsulation ... */
1259 /* the rest of the implementation is just working fine :-( */
1260 /*gtk_widget_show(compressed_cb);*/
1261 g_object_set_data(G_OBJECT(file_save_as_w), "compressed", compressed_cb);
1262 gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(cfile.cd_t));
1264 g_signal_connect(file_save_as_w, "destroy",
1265 G_CALLBACK(file_save_as_destroy_cb), NULL);
1267 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT) {
1268 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1270 window_destroy(file_save_as_w);
1276 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1278 file_save_as_cmd(after_save_no_action, NULL);
1282 /* all tests ok, we only have to save the file */
1283 /* (and probably continue with a pending operation) */
1285 file_save_as_cb(GtkWidget *w _U_, gpointer fs) {
1288 GtkWidget *compressed_cb;
1291 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1293 compressed_cb = g_object_get_data(G_OBJECT(file_save_as_w), "compressed");
1295 /* XXX - if the user requests to save to an already existing filename, */
1296 /* ask in a dialog if that's intended */
1297 /* currently, cf_save() will simply deny it */
1299 /* Write out the packets (all, or only the ones from the current
1300 range) to the file with the specified name. */
1301 if (cf_save(&cfile, cf_name, &range, filetype,
1302 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressed_cb))) != CF_OK) {
1303 /* The write failed; don't dismiss the open dialog box,
1304 just leave it around so that the user can, after they
1305 dismiss the alert box popped up for the error, try again. */
1307 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1308 * as this will prevent the user from closing the now existing error
1309 * message, simply close the dialog (this is the best we can do here). */
1311 window_destroy(GTK_WIDGET (fs));
1315 /* The write succeeded; get rid of the file selection box. */
1316 /* cf_save() might already closed our dialog! */
1318 window_destroy(GTK_WIDGET (fs));
1320 /* Save the directory name for future file dialogs. */
1321 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1322 set_last_open_dir(dirname);
1325 /* we have finished saving, do we have pending things to do? */
1326 switch(action_after_save_g) {
1327 case(after_save_no_action):
1329 case(after_save_open_dialog):
1330 file_open_cmd(action_after_save_data_g);
1332 case(after_save_open_recent_file):
1333 menu_open_recent_file_cmd(action_after_save_data_g);
1335 case(after_save_open_dnd_file):
1336 dnd_open_file_cmd(action_after_save_data_g);
1338 case(after_save_merge_dialog):
1339 file_merge_cmd(action_after_save_data_g);
1342 case(after_save_capture_dialog):
1343 capture_start_confirmed();
1346 case(after_save_close_file):
1349 case(after_save_exit):
1353 g_assert_not_reached();
1356 action_after_save_g = after_save_no_action;
1360 static void file_save_as_exists_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1364 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data));
1370 file_save_as_cb(NULL, data);
1372 case(ESD_BTN_CANCEL):
1373 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1374 * as this will prevent the user from closing the now existing error
1375 * message, simply close the dialog (this is the best we can do here). */
1377 window_destroy(file_save_as_w);
1380 g_assert_not_reached();
1386 /* user pressed "Save" dialog "Ok" button */
1388 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1392 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1394 /* Perhaps the user specified a directory instead of a file.
1395 Check whether they did. */
1396 if (test_for_directory(cf_name) == EISDIR) {
1397 /* It's a directory - set the file selection box to display that
1398 directory, and leave the selection box displayed. */
1399 set_last_open_dir(cf_name);
1401 file_selection_set_current_folder(fs, get_last_open_dir());
1405 /* Check whether the range is valid. */
1406 if (!range_check_validity(&range)) {
1407 /* The range isn't valid; don't dismiss the open dialog box,
1408 just leave it around so that the user can, after they
1409 dismiss the alert box popped up for the error, try again. */
1411 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1412 * as this will prevent the user from closing the now existing error
1413 * message, simply close the dialog (this is the best we can do here). */
1415 window_destroy(GTK_WIDGET (fs));
1421 * Check that the from file is not the same as to file
1422 * We do it here so we catch all cases ...
1423 * Unfortunately, the file requester gives us an absolute file
1424 * name and the read file name may be relative (if supplied on
1425 * the command line). From Joerg Mayer.
1427 if (files_identical(cfile.filename, cf_name)) {
1428 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1429 "%sCapture file: \"%s\" identical to loaded file!%s\n\n"
1430 "Please choose a different filename.",
1431 simple_dialog_primary_start(), cf_name, simple_dialog_primary_end());
1433 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1434 * as this will prevent the user from closing the now existing error
1435 * message, simply close the dialog (this is the best we can do here). */
1437 window_destroy(GTK_WIDGET (fs));
1442 /* don't show the dialog while saving (or asking) */
1443 gtk_widget_hide(GTK_WIDGET (fs));
1445 /* it the file doesn't exist, simply try to save it */
1446 if (!file_exists(cf_name)) {
1447 file_save_as_cb(NULL, fs);
1452 /* the file exists, ask the user to remove it first */
1453 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
1454 "%sA file named \"%s\" already exists.%s\n\n"
1455 "Do you want to replace it with the capture you are saving?",
1456 simple_dialog_primary_start(), cf_name, simple_dialog_primary_end());
1457 simple_dialog_set_cb(dialog, file_save_as_exists_answered_cb, fs);
1463 file_save_as_destroy(void)
1466 window_destroy(file_save_as_w);
1470 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1472 /* Note that we no longer have a "Save Capture File As" dialog box. */
1473 file_save_as_w = NULL;
1476 /* Reload a file using the current read and display filters */
1478 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1482 /******************** Color Filters *********************************/
1484 * Keep a static pointer to the current "Color Export" window, if
1485 * any, so that if somebody tries to do "Export"
1486 * while there's already a "Color Export" window up, we just pop
1487 * up the existing one, rather than creating a new one.
1489 static GtkWidget *file_color_import_w;
1491 /* sets the file path to the global color filter file.
1492 WARNING: called by both the import and the export dialog.
1495 color_global_cb(GtkWidget *widget _U_, gpointer data)
1497 GtkWidget *fs_widget = data;
1500 /* decide what file to open (from dfilter code) */
1501 path = get_datafile_path("colorfilters");
1503 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1508 /* Import color filters */
1510 file_color_import_cmd_cb(GtkWidget *color_filters, gpointer filter_list _U_)
1513 win32_import_color_file(GDK_WINDOW_HWND(top_level->window), color_filters);
1515 GtkWidget *main_vb, *cfglobal_but;
1517 /* No Apply button, and "OK" just sets our text widget, it doesn't
1518 activate it (i.e., it doesn't cause us to try to open the file). */
1520 if (file_color_import_w != NULL) {
1521 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1522 reactivate_window(file_color_import_w);
1526 file_color_import_w = file_selection_new("Wireshark: Import Color Filters",
1527 FILE_SELECTION_OPEN);
1529 /* Container for each row of widgets */
1530 main_vb = gtk_vbox_new(FALSE, 3);
1531 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1532 file_selection_set_extra_widget(file_color_import_w, main_vb);
1533 gtk_widget_show(main_vb);
1536 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1537 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1538 g_signal_connect(cfglobal_but, "clicked",
1539 G_CALLBACK(color_global_cb), file_color_import_w);
1540 gtk_widget_show(cfglobal_but);
1542 g_signal_connect(file_color_import_w, "destroy",
1543 G_CALLBACK(file_color_import_destroy_cb), NULL);
1546 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1548 file_color_import_ok_cb(file_color_import_w, color_filters);
1550 else window_destroy(file_color_import_w);
1555 file_color_import_ok_cb(GtkWidget *w, gpointer color_filters) {
1557 GtkWidget *fs = gtk_widget_get_toplevel(w);
1559 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1561 /* Perhaps the user specified a directory instead of a file.
1562 Check whether they did. */
1563 if (test_for_directory(cf_name) == EISDIR) {
1564 /* It's a directory - set the file selection box to display that
1565 directory, don't try to open the directory as a color filter file. */
1566 set_last_open_dir(cf_name);
1568 file_selection_set_current_folder(fs, get_last_open_dir());
1572 /* Try to open the color filter file. */
1574 if (!color_filters_import(cf_name, color_filters)) {
1575 /* We couldn't open it; don't dismiss the open dialog box,
1576 just leave it around so that the user can, after they
1577 dismiss the alert box popped up for the open error,
1580 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1581 * as this will prevent the user from closing the now existing error
1582 * message, simply close the dialog (this is the best we can do here). */
1583 window_destroy(GTK_WIDGET (fs));
1588 /* We've crossed the Rubicon; get rid of the file selection box. */
1589 window_destroy(GTK_WIDGET (fs));
1591 /* Save the name of the containing directory specified in the path name,
1592 if any; we can write over cf_name, which is a good thing, given that
1593 "get_dirname()" does write over its argument. */
1594 s = get_dirname(cf_name);
1595 set_last_open_dir(s);
1596 #ifndef NEW_PACKET_LIST
1597 gtk_widget_grab_focus(packet_list);
1604 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1606 /* Note that we no longer have a "Open Capture File" dialog box. */
1607 file_color_import_w = NULL;
1610 static GtkWidget *file_color_export_w;
1612 * Set the "Export only selected filters" toggle button as appropriate for
1613 * the current output file type and count of selected filters.
1615 * Called when the "Export" dialog box is created and when the selected
1619 color_set_export_selected_sensitive(GtkWidget * cfselect_cb)
1621 if (file_color_export_w == NULL) {
1622 /* We don't currently have an "Export" dialog box up. */
1626 /* We can request that only the selected filters be saved only if
1627 there *are* selected filters. */
1628 if (color_selected_count() != 0)
1629 gtk_widget_set_sensitive(cfselect_cb, TRUE);
1631 /* Force the "Export only selected filters" toggle to "false", turn
1632 off the flag it controls. */
1633 color_selected = FALSE;
1634 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfselect_cb), FALSE);
1635 gtk_widget_set_sensitive(cfselect_cb, FALSE);
1640 color_toggle_selected_cb(GtkWidget *widget, gpointer data _U_)
1642 color_selected = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1646 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list)
1649 win32_export_color_file(GDK_WINDOW_HWND(top_level->window), filter_list);
1651 GtkWidget *main_vb, *cfglobal_but;
1652 GtkWidget *cfselect_cb;
1654 if (file_color_export_w != NULL) {
1655 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1656 reactivate_window(file_color_export_w);
1660 color_selected = FALSE;
1662 file_color_export_w = file_selection_new("Wireshark: Export Color Filters",
1663 FILE_SELECTION_SAVE);
1665 /* Container for each row of widgets */
1666 main_vb = gtk_vbox_new(FALSE, 3);
1667 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1668 file_selection_set_extra_widget(file_color_export_w, main_vb);
1669 gtk_widget_show(main_vb);
1671 cfselect_cb = gtk_check_button_new_with_label("Export only selected filters");
1672 gtk_container_add(GTK_CONTAINER(main_vb), cfselect_cb);
1673 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfselect_cb), FALSE);
1674 g_signal_connect(cfselect_cb, "toggled",
1675 G_CALLBACK(color_toggle_selected_cb), NULL);
1676 gtk_widget_show(cfselect_cb);
1677 color_set_export_selected_sensitive(cfselect_cb);
1679 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1680 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1681 g_signal_connect(cfglobal_but, "clicked",
1682 G_CALLBACK(color_global_cb), file_color_export_w);
1683 gtk_widget_show(cfglobal_but);
1685 g_signal_connect(file_color_export_w, "destroy",
1686 G_CALLBACK(file_color_export_destroy_cb), NULL);
1688 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1690 file_color_export_ok_cb(file_color_export_w, filter_list);
1692 else window_destroy(file_color_export_w);
1697 file_color_export_ok_cb(GtkWidget *w, gpointer filter_list) {
1700 GtkWidget *fs = gtk_widget_get_toplevel(w);
1702 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1704 /* Perhaps the user specified a directory instead of a file.
1705 Check whether they did. */
1706 if (test_for_directory(cf_name) == EISDIR) {
1707 /* It's a directory - set the file selection box to display that
1708 directory, and leave the selection box displayed. */
1709 set_last_open_dir(cf_name);
1711 file_selection_set_current_folder(fs, get_last_open_dir());
1715 /* Write out the filters (all, or only the ones that are currently
1716 displayed or selected) to the file with the specified name. */
1718 if (!color_filters_export(cf_name, filter_list, color_selected))
1720 /* The write failed; don't dismiss the open dialog box,
1721 just leave it around so that the user can, after they
1722 dismiss the alert box popped up for the error, try again. */
1725 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1726 * as this will prevent the user from closing the now existing error
1727 * message, simply close the dialog (this is the best we can do here). */
1728 window_destroy(GTK_WIDGET (fs));
1733 /* The write succeeded; get rid of the file selection box. */
1734 window_destroy(GTK_WIDGET (fs));
1736 /* Save the directory name for future file dialogs. */
1737 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1738 set_last_open_dir(dirname);
1743 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1745 file_color_export_w = NULL;