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"
65 #include "gtk/capture_dlg.h"
67 #include "gtk/stock_icons.h"
68 #include "gtk/range_utils.h"
69 #include "gtk/filter_autocomplete.h"
72 #include <gdk/gdkwin32.h>
74 #include "gtk/file_dlg_win32.h"
78 static void file_open_ok_cb(GtkWidget *w, gpointer fs);
79 static void file_open_destroy_cb(GtkWidget *win, gpointer user_data);
80 static void file_merge_ok_cb(GtkWidget *w, gpointer fs);
81 static void file_merge_destroy_cb(GtkWidget *win, gpointer user_data);
82 static void select_file_type_cb(GtkWidget *w, gpointer data);
83 static void file_save_as_ok_cb(GtkWidget *w, gpointer fs);
84 static void file_save_as_destroy_cb(GtkWidget *win, gpointer user_data);
85 static void file_color_import_ok_cb(GtkWidget *w, gpointer filter_list);
86 static void file_color_import_destroy_cb(GtkWidget *win, gpointer user_data);
87 static void file_color_export_ok_cb(GtkWidget *w, gpointer filter_list);
88 static void file_color_export_destroy_cb(GtkWidget *win, gpointer user_data);
89 static void set_file_type_list(GtkWidget *option_menu);
91 #define E_FILE_M_RESOLVE_KEY "file_dlg_mac_resolve_key"
92 #define E_FILE_N_RESOLVE_KEY "file_dlg_network_resolve_key"
93 #define E_FILE_T_RESOLVE_KEY "file_dlg_transport_resolve_key"
95 #define E_MERGE_PREPEND_KEY "merge_dlg_prepend_key"
96 #define E_MERGE_CHRONO_KEY "merge_dlg_chrono_key"
97 #define E_MERGE_APPEND_KEY "merge_dlg_append_key"
100 #define PREVIEW_TABLE_KEY "preview_table_key"
101 #define PREVIEW_FILENAME_KEY "preview_filename_key"
102 #define PREVIEW_FORMAT_KEY "preview_format_key"
103 #define PREVIEW_SIZE_KEY "preview_size_key"
104 #define PREVIEW_ELAPSED_KEY "preview_elapsed_key"
105 #define PREVIEW_PACKETS_KEY "preview_packets_key"
106 #define PREVIEW_FIRST_KEY "preview_first_key"
110 * Keep a static pointer to the current "Save Capture File As" window, if
111 * any, so that if somebody tries to do "File:Save" or "File:Save As"
112 * while there's already a "Save Capture File As" window up, we just pop
113 * up the existing one, rather than creating a new one.
115 static GtkWidget *file_save_as_w;
117 /* XXX - can we make these not be static? */
118 static packet_range_t range;
119 static gboolean color_selected;
121 static GtkWidget *cfselect_cb;
122 static GtkWidget *ft_om;
123 static GtkWidget *range_tb;
125 #define PREVIEW_STR_MAX 200
128 /* set a new filename for the preview widget */
130 preview_set_filename(GtkWidget *prev, const gchar *cf_name)
136 gchar string_buff[PREVIEW_STR_MAX];
140 /* init preview labels */
141 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FILENAME_KEY);
142 gtk_label_set_text(GTK_LABEL(label), "-");
143 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
144 gtk_label_set_text(GTK_LABEL(label), "-");
145 label = g_object_get_data(G_OBJECT(prev), PREVIEW_SIZE_KEY);
146 gtk_label_set_text(GTK_LABEL(label), "-");
147 label = g_object_get_data(G_OBJECT(prev), PREVIEW_ELAPSED_KEY);
148 gtk_label_set_text(GTK_LABEL(label), "-");
149 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
150 gtk_label_set_text(GTK_LABEL(label), "-");
151 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FIRST_KEY);
152 gtk_label_set_text(GTK_LABEL(label), "-");
158 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FILENAME_KEY);
159 gtk_label_set_text(GTK_LABEL(label), get_basename(cf_name));
161 if (test_for_directory(cf_name) == EISDIR) {
162 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
163 gtk_label_set_text(GTK_LABEL(label), "directory");
167 wth = wtap_open_offline(cf_name, &err, &err_info, TRUE);
169 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
170 if(err == WTAP_ERR_FILE_UNKNOWN_FORMAT) {
171 gtk_label_set_text(GTK_LABEL(label), "unknown file format");
173 gtk_label_set_text(GTK_LABEL(label), "error opening file");
178 /* Find the size of the file. */
179 filesize = wtap_file_size(wth, &err);
180 if (filesize == -1) {
181 gtk_label_set_text(GTK_LABEL(label), "error getting file size");
185 g_snprintf(string_buff, PREVIEW_STR_MAX, "%" G_GINT64_MODIFIER "d bytes", filesize);
186 label = g_object_get_data(G_OBJECT(prev), PREVIEW_SIZE_KEY);
187 gtk_label_set_text(GTK_LABEL(label), string_buff);
190 g_strlcpy(string_buff, wtap_file_type_string(wtap_file_type(wth)), PREVIEW_STR_MAX);
191 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FORMAT_KEY);
192 gtk_label_set_text(GTK_LABEL(label), string_buff);
198 /* do a preview run on the currently selected capture file */
200 preview_do(GtkWidget *prev, wtap *wth)
203 unsigned int elapsed_time;
209 const struct wtap_pkthdr *phdr;
210 double start_time = 0; /* seconds, with nsec resolution */
211 double stop_time = 0; /* seconds, with nsec resolution */
213 unsigned int packets = 0;
214 gboolean is_breaked = FALSE;
215 gchar string_buff[PREVIEW_STR_MAX];
221 while ( (wtap_read(wth, &err, &err_info, &data_offset)) ) {
222 phdr = wtap_phdr(wth);
223 cur_time = wtap_nstime_to_sec(&phdr->ts);
225 start_time = cur_time;
226 stop_time = cur_time;
228 if (cur_time < start_time) {
229 start_time = cur_time;
231 if (cur_time > stop_time){
232 stop_time = cur_time;
236 if(packets%1000 == 0) {
237 /* do we have a timeout? */
239 if(time_current-time_preview >= (time_t) prefs.gui_fileopen_preview) {
247 g_snprintf(string_buff, PREVIEW_STR_MAX, "error after reading %u packets", packets);
248 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
249 gtk_label_set_text(GTK_LABEL(label), string_buff);
256 g_snprintf(string_buff, PREVIEW_STR_MAX, "more than %u packets (preview timeout)", packets);
258 g_snprintf(string_buff, PREVIEW_STR_MAX, "%u", packets);
260 label = g_object_get_data(G_OBJECT(prev), PREVIEW_PACKETS_KEY);
261 gtk_label_set_text(GTK_LABEL(label), string_buff);
264 ti_time = (long)start_time;
265 ti_tm = localtime( &ti_time );
267 g_snprintf(string_buff, PREVIEW_STR_MAX,
268 "%04d-%02d-%02d %02d:%02d:%02d",
269 ti_tm->tm_year + 1900,
276 g_snprintf(string_buff, PREVIEW_STR_MAX, "?");
278 label = g_object_get_data(G_OBJECT(prev), PREVIEW_FIRST_KEY);
279 gtk_label_set_text(GTK_LABEL(label), string_buff);
282 elapsed_time = (unsigned int)(stop_time-start_time);
283 if(elapsed_time/86400) {
284 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u days %02u:%02u:%02u",
285 elapsed_time/86400, elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
287 g_snprintf(string_buff, PREVIEW_STR_MAX, "%02u:%02u:%02u",
288 elapsed_time%86400/3600, elapsed_time%3600/60, elapsed_time%60);
291 g_snprintf(string_buff, PREVIEW_STR_MAX, "unknown");
293 label = g_object_get_data(G_OBJECT(prev), PREVIEW_ELAPSED_KEY);
294 gtk_label_set_text(GTK_LABEL(label), string_buff);
300 /* as the dialog layout will look very ugly when using the file chooser preview mechanism,
301 simply use the same layout as in GTK2.0 */
303 update_preview_cb (GtkFileChooser *file_chooser, gpointer data)
305 GtkWidget *prev = GTK_WIDGET (data);
307 gboolean have_preview;
309 cf_name = gtk_file_chooser_get_preview_filename (file_chooser);
311 have_preview = preview_set_filename(prev, cf_name);
316 gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
321 /* the filename text entry changed */
323 file_open_entry_changed(GtkWidget *w _U_, gpointer file_sel)
325 GtkWidget *prev = g_object_get_data(G_OBJECT(file_sel), PREVIEW_TABLE_KEY);
327 gboolean have_preview;
330 /* get the filename */
331 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_sel));
333 /* set the filename to the preview */
334 wth = preview_set_filename(prev, cf_name);
335 have_preview = (wth != NULL);
339 /* make the preview widget sensitive */
340 gtk_widget_set_sensitive(prev, have_preview);
342 /* make the open/save/... dialog button sensitive */
344 gtk_dialog_set_response_sensitive(file_sel, GTK_RESPONSE_ACCEPT, 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, const gchar *title, const 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.0f, 0.5f);
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.0f, 0.5f);
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, const gchar *title, const 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 gtk_widget_set_size_request(label, DEF_WIDTH/3, -1);
401 g_object_set_data(G_OBJECT(table), PREVIEW_FILENAME_KEY, label);
402 label = add_string_to_table(table, &row, "Format:", "-");
403 g_object_set_data(G_OBJECT(table), PREVIEW_FORMAT_KEY, label);
404 label = add_string_to_table(table, &row, "Size:", "-");
405 g_object_set_data(G_OBJECT(table), PREVIEW_SIZE_KEY, label);
406 label = add_string_to_table(table, &row, "Packets:", "-");
407 g_object_set_data(G_OBJECT(table), PREVIEW_PACKETS_KEY, label);
408 label = add_string_to_table(table, &row, "First Packet:", "-");
409 g_object_set_data(G_OBJECT(table), PREVIEW_FIRST_KEY, label);
410 label = add_string_to_table(table, &row, "Elapsed time:", "-");
411 g_object_set_data(G_OBJECT(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)
429 win32_open_file(GDK_WINDOW_HWND(top_level->window));
431 GtkWidget *main_hb, *main_vb, *filter_hbox, *filter_bt, *filter_te,
432 *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, *prev;
433 GtkTooltips *tooltips = gtk_tooltips_new();
434 /* No Apply button, and "OK" just sets our text widget, it doesn't
435 activate it (i.e., it doesn't cause us to try to open the file). */
436 static construct_args_t args = {
437 "Wireshark: Read Filter",
443 if (file_open_w != NULL) {
444 /* There's already an "Open Capture File" dialog box; reactivate it. */
445 reactivate_window(file_open_w);
449 file_open_w = file_selection_new("Wireshark: Open Capture File",
450 FILE_SELECTION_OPEN);
451 /* it's annoying, that the file chooser dialog is already shown here,
452 so we cannot use the correct gtk_window_set_default_size() to resize it */
453 gtk_widget_set_size_request(file_open_w, DEF_WIDTH, DEF_HEIGHT);
455 switch (prefs.gui_fileopen_style) {
457 case FO_STYLE_LAST_OPENED:
458 /* The user has specified that we should start out in the last directory
459 we looked in. If we've already opened a file, use its containing
460 directory, if we could determine it, as the directory, otherwise
461 use the "last opened" directory saved in the preferences file if
463 /* This is now the default behaviour in file_selection_new() */
466 case FO_STYLE_SPECIFIED:
467 /* The user has specified that we should always start out in a
468 specified directory; if they've specified that directory,
469 start out by showing the files in that dir. */
470 if (prefs.gui_fileopen_dir[0] != '\0')
471 file_selection_set_current_folder(file_open_w, prefs.gui_fileopen_dir);
476 main_hb = gtk_hbox_new(FALSE, 3);
477 file_selection_set_extra_widget(file_open_w, main_hb);
478 gtk_widget_show(main_hb);
480 /* Container for each row of widgets */
481 main_vb = gtk_vbox_new(FALSE, 3);
482 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
483 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
484 gtk_widget_show(main_vb);
487 filter_hbox = gtk_hbox_new(FALSE, 1);
488 gtk_container_set_border_width(GTK_CONTAINER(filter_hbox), 0);
489 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
490 gtk_widget_show(filter_hbox);
492 filter_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
493 g_signal_connect(filter_bt, "clicked",
494 G_CALLBACK(display_filter_construct_cb), &args);
495 g_signal_connect(filter_bt, "destroy",
496 G_CALLBACK(filter_button_destroy_cb), NULL);
497 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
498 gtk_widget_show(filter_bt);
499 gtk_tooltips_set_tip(tooltips, filter_bt,
500 "Open the \"Display Filter\" dialog, to edit/apply filters", NULL);
502 filter_te = gtk_entry_new();
503 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
504 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
505 g_signal_connect(filter_te, "changed",
506 G_CALLBACK(filter_te_syntax_check_cb), NULL);
507 g_object_set_data(G_OBJECT(filter_hbox), E_FILT_AUTOCOMP_PTR_KEY, NULL);
508 g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
509 g_signal_connect(file_open_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
510 colorize_filter_te_as_empty(filter_te);
511 gtk_widget_show(filter_te);
512 gtk_tooltips_set_tip(tooltips, filter_te, "Enter a display filter.", NULL);
514 g_object_set_data(G_OBJECT(file_open_w), E_RFILTER_TE_KEY, filter_te);
516 /* resolve buttons */
517 m_resolv_cb = gtk_check_button_new_with_mnemonic("Enable _MAC name resolution");
518 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_resolv_cb),
519 g_resolv_flags & RESOLV_MAC);
520 gtk_box_pack_start(GTK_BOX(main_vb), m_resolv_cb, FALSE, FALSE, 0);
521 g_object_set_data(G_OBJECT(file_open_w),
522 E_FILE_M_RESOLVE_KEY, m_resolv_cb);
523 gtk_widget_show(m_resolv_cb);
525 n_resolv_cb = gtk_check_button_new_with_mnemonic("Enable _network name resolution");
526 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(n_resolv_cb),
527 g_resolv_flags & RESOLV_NETWORK);
528 gtk_box_pack_start(GTK_BOX(main_vb), n_resolv_cb, FALSE, FALSE, 0);
529 gtk_widget_show(n_resolv_cb);
530 g_object_set_data(G_OBJECT(file_open_w), E_FILE_N_RESOLVE_KEY, n_resolv_cb);
531 t_resolv_cb = gtk_check_button_new_with_mnemonic("Enable _transport name resolution");
532 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(t_resolv_cb),
533 g_resolv_flags & RESOLV_TRANSPORT);
534 gtk_box_pack_start(GTK_BOX(main_vb), t_resolv_cb, FALSE, FALSE, 0);
535 gtk_widget_show(t_resolv_cb);
536 g_object_set_data(G_OBJECT(file_open_w), E_FILE_T_RESOLVE_KEY, t_resolv_cb);
538 g_signal_connect(file_open_w, "destroy",
539 G_CALLBACK(file_open_destroy_cb), NULL);
542 prev = preview_new();
543 g_object_set_data(G_OBJECT(file_open_w), PREVIEW_TABLE_KEY, prev);
544 gtk_widget_show_all(prev);
545 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
547 g_signal_connect(GTK_FILE_CHOOSER(file_open_w), "selection-changed",
548 G_CALLBACK(file_open_entry_changed), file_open_w);
549 file_open_entry_changed(file_open_w, file_open_w);
551 g_object_set_data(G_OBJECT(file_open_w), E_DFILTER_TE_KEY,
552 g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
553 if (gtk_dialog_run(GTK_DIALOG(file_open_w)) == GTK_RESPONSE_ACCEPT)
555 file_open_ok_cb(file_open_w, file_open_w);
557 else window_destroy(file_open_w);
561 static void file_open_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
565 /* save file first */
566 file_save_as_cmd(after_save_open_dialog, data);
568 case(ESD_BTN_DONT_SAVE):
572 case(ESD_BTN_CANCEL):
575 g_assert_not_reached();
580 file_open_cmd_cb(GtkWidget *widget, gpointer data _U_) {
583 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
584 /* user didn't save his current file, ask him */
585 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
586 "%sSave capture file before opening a new one?%s\n\n"
587 "If you open a new capture file without saving, your capture data will be discarded.",
588 simple_dialog_primary_start(), simple_dialog_primary_end());
589 simple_dialog_set_cb(dialog, file_open_answered_cb, widget);
591 /* unchanged file, just open a new one */
592 file_open_cmd(widget);
596 /* user pressed "open" button */
598 file_open_ok_cb(GtkWidget *w, gpointer fs) {
600 const gchar *rfilter;
601 GtkWidget *filter_te, *m_resolv_cb, *n_resolv_cb, *t_resolv_cb;
602 dfilter_t *rfcode = NULL;
605 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
606 filter_te = g_object_get_data(G_OBJECT(w), E_RFILTER_TE_KEY);
607 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
608 if (!dfilter_compile(rfilter, &rfcode)) {
609 bad_dfilter_alert_box(rfilter);
614 /* Perhaps the user specified a directory instead of a file.
615 Check whether they did. */
616 if (test_for_directory(cf_name) == EISDIR) {
617 /* It's a directory - set the file selection box to display that
618 directory, don't try to open the directory as a capture file. */
619 set_last_open_dir(cf_name);
621 file_selection_set_current_folder(fs, get_last_open_dir());
625 /* Try to open the capture file. */
626 if (cf_open(&cfile, cf_name, FALSE, &err) != CF_OK) {
627 /* We couldn't open it; don't dismiss the open dialog box,
628 just leave it around so that the user can, after they
629 dismiss the alert box popped up for the open error,
632 dfilter_free(rfcode);
635 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
636 * as this will prevent the user from closing the now existing error
637 * message, simply close the dialog (this is the best we can do here). */
639 window_destroy(file_open_w);
644 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
645 it closed the previous capture file, and thus destroyed any
646 previous read filter attached to "cf"). */
647 cfile.rfcode = rfcode;
649 /* Set the global resolving variable */
650 g_resolv_flags = prefs.name_resolve;
651 m_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_M_RESOLVE_KEY);
652 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (m_resolv_cb)))
653 g_resolv_flags |= RESOLV_MAC;
655 g_resolv_flags &= ~RESOLV_MAC;
656 n_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_N_RESOLVE_KEY);
657 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (n_resolv_cb)))
658 g_resolv_flags |= RESOLV_NETWORK;
660 g_resolv_flags &= ~RESOLV_NETWORK;
661 t_resolv_cb = g_object_get_data(G_OBJECT(w), E_FILE_T_RESOLVE_KEY);
662 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (t_resolv_cb)))
663 g_resolv_flags |= RESOLV_TRANSPORT;
665 g_resolv_flags &= ~RESOLV_TRANSPORT;
667 /* We've crossed the Rubicon; get rid of the file selection box. */
668 window_destroy(GTK_WIDGET (fs));
670 switch (cf_read(&cfile)) {
674 /* Just because we got an error, that doesn't mean we were unable
675 to read any of the file; we handle what we could get from the
679 case CF_READ_ABORTED:
680 /* The user bailed out of re-reading the capture file; the
681 capture file has been closed - just free the capture file name
682 string and return (without changing the last containing
688 /* Save the name of the containing directory specified in the path name,
689 if any; we can write over cf_name, which is a good thing, given that
690 "get_dirname()" does write over its argument. */
691 s = get_dirname(cf_name);
692 set_last_open_dir(s);
693 gtk_widget_grab_focus(packet_list);
699 file_open_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
701 /* Note that we no longer have a "Open Capture File" dialog box. */
706 * Keep a static pointer to the current "Merge Capture File" window, if
707 * any, so that if somebody tries to do "File:Merge" while there's already
708 * an "Merge Capture File" window up, we just pop up the existing one,
709 * rather than creating a new one.
711 static GtkWidget *file_merge_w;
713 /* Merge existing with another file */
715 file_merge_cmd(GtkWidget *w)
718 win32_merge_file(GDK_WINDOW_HWND(top_level->window));
719 packet_list_freeze();
722 GtkWidget *main_hb, *main_vb, *ft_hb, *ft_lb, *filter_hbox,
723 *filter_bt, *filter_te, *prepend_rb, *chrono_rb,
725 GtkTooltips *tooltips = gtk_tooltips_new();
726 /* No Apply button, and "OK" just sets our text widget, it doesn't
727 activate it (i.e., it doesn't cause us to try to open the file). */
728 static construct_args_t args = {
729 "Wireshark: Read Filter",
735 if (file_merge_w != NULL) {
736 /* There's already an "Merge Capture File" dialog box; reactivate it. */
737 reactivate_window(file_merge_w);
741 /* Default to saving all packets, in the file's current format. */
742 filetype = cfile.cd_t;
744 file_merge_w = file_selection_new("Wireshark: Merge with Capture File",
745 FILE_SELECTION_OPEN);
746 /* it's annoying, that the file chooser dialog is already shown here,
747 so we cannot use the correct gtk_window_set_default_size() to resize it */
748 gtk_widget_set_size_request(file_merge_w, DEF_WIDTH, DEF_HEIGHT);
750 switch (prefs.gui_fileopen_style) {
752 case FO_STYLE_LAST_OPENED:
753 /* The user has specified that we should start out in the last directory
754 we looked in. If we've already opened a file, use its containing
755 directory, if we could determine it, as the directory, otherwise
756 use the "last opened" directory saved in the preferences file if
758 /* This is now the default behaviour in file_selection_new() */
761 case FO_STYLE_SPECIFIED:
762 /* The user has specified that we should always start out in a
763 specified directory; if they've specified that directory,
764 start out by showing the files in that dir. */
765 if (prefs.gui_fileopen_dir[0] != '\0')
766 file_selection_set_current_folder(file_merge_w, prefs.gui_fileopen_dir);
770 main_hb = gtk_hbox_new(FALSE, 3);
771 file_selection_set_extra_widget(file_merge_w, main_hb);
772 gtk_widget_show(main_hb);
774 /* Container for each row of widgets */
775 main_vb = gtk_vbox_new(FALSE, 3);
776 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
777 gtk_box_pack_start(GTK_BOX(main_hb), main_vb, FALSE, FALSE, 0);
778 gtk_widget_show(main_vb);
782 ft_hb = gtk_hbox_new(FALSE, 3);
783 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
784 gtk_widget_show(ft_hb);
786 ft_lb = gtk_label_new("Merged output file type:");
787 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
788 gtk_widget_show(ft_lb);
790 ft_om = gtk_option_menu_new();
792 /* Generate the list of file types we can save. */
793 set_file_type_list(ft_om);
794 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
795 gtk_widget_show(ft_om);
797 filter_hbox = gtk_hbox_new(FALSE, 1);
798 gtk_container_set_border_width(GTK_CONTAINER(filter_hbox), 0);
799 gtk_box_pack_start(GTK_BOX(main_vb), filter_hbox, FALSE, FALSE, 0);
800 gtk_widget_show(filter_hbox);
802 filter_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_DISPLAY_FILTER_ENTRY);
803 g_signal_connect(filter_bt, "clicked",
804 G_CALLBACK(display_filter_construct_cb), &args);
805 g_signal_connect(filter_bt, "destroy",
806 G_CALLBACK(filter_button_destroy_cb), NULL);
807 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_bt, FALSE, TRUE, 0);
808 gtk_widget_show(filter_bt);
809 gtk_tooltips_set_tip(tooltips, filter_bt,
810 "Open the \"Display Filter\" dialog, to edit/apply filters", NULL);
812 filter_te = gtk_entry_new();
813 g_object_set_data(G_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
814 gtk_box_pack_start(GTK_BOX(filter_hbox), filter_te, TRUE, TRUE, 3);
815 g_signal_connect(filter_te, "changed",
816 G_CALLBACK(filter_te_syntax_check_cb), NULL);
817 g_object_set_data(G_OBJECT(filter_hbox), E_FILT_AUTOCOMP_PTR_KEY, NULL);
818 g_signal_connect(filter_te, "key-press-event", G_CALLBACK (filter_string_te_key_pressed_cb), NULL);
819 g_signal_connect(file_merge_w, "key-press-event", G_CALLBACK (filter_parent_dlg_key_pressed_cb), NULL);
820 colorize_filter_te_as_empty(filter_te);
821 gtk_widget_show(filter_te);
822 gtk_tooltips_set_tip(tooltips, filter_te, "Enter a display filter.", NULL);
824 g_object_set_data(G_OBJECT(file_merge_w), E_RFILTER_TE_KEY, filter_te);
826 prepend_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL,
827 "Prepend packets to existing file");
828 gtk_tooltips_set_tip(tooltips, prepend_rb,
829 "The resulting file contains the packets from the selected, followed by the packets from the currently loaded file,"
830 " the packet timestamps will be ignored.", NULL);
831 gtk_box_pack_start(GTK_BOX(main_vb), prepend_rb, FALSE, FALSE, 0);
832 g_object_set_data(G_OBJECT(file_merge_w),
833 E_MERGE_PREPEND_KEY, prepend_rb);
834 gtk_widget_show(prepend_rb);
836 chrono_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(prepend_rb), "Merge packets chronologically");
837 gtk_tooltips_set_tip(tooltips, chrono_rb,
838 "The resulting file contains all the packets from the currently loaded and the selected file,"
839 " sorted by the packet timestamps.", NULL);
840 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chrono_rb), TRUE);
841 gtk_box_pack_start(GTK_BOX(main_vb), chrono_rb, FALSE, FALSE, 0);
842 gtk_widget_show(chrono_rb);
843 g_object_set_data(G_OBJECT(file_merge_w), E_MERGE_CHRONO_KEY, chrono_rb);
845 append_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(prepend_rb), "Append packets to existing file");
846 gtk_tooltips_set_tip(tooltips, append_rb,
847 "The resulting file contains the packets from the currently loaded, followed by the packets from the selected file,"
848 " the packet timestamps will be ignored.", NULL);
849 gtk_box_pack_start(GTK_BOX(main_vb), append_rb, FALSE, FALSE, 0);
850 gtk_widget_show(append_rb);
851 g_object_set_data(G_OBJECT(file_merge_w), E_MERGE_APPEND_KEY, append_rb);
853 g_signal_connect(file_merge_w, "destroy",
854 G_CALLBACK(file_merge_destroy_cb), NULL);
857 prev = preview_new();
858 g_object_set_data(G_OBJECT(file_merge_w), PREVIEW_TABLE_KEY, prev);
859 gtk_widget_show_all(prev);
860 gtk_box_pack_start(GTK_BOX(main_hb), prev, TRUE, TRUE, 0);
862 g_signal_connect(GTK_FILE_CHOOSER(file_merge_w), "selection-changed",
863 G_CALLBACK(file_open_entry_changed), file_merge_w);
864 file_open_entry_changed(file_merge_w, file_merge_w);
866 g_object_set_data(G_OBJECT(file_merge_w), E_DFILTER_TE_KEY,
867 g_object_get_data(G_OBJECT(w), E_DFILTER_TE_KEY));
868 if (gtk_dialog_run(GTK_DIALOG(file_merge_w)) == GTK_RESPONSE_ACCEPT)
870 file_merge_ok_cb(file_merge_w, file_merge_w);
872 else window_destroy(file_merge_w);
876 static void file_merge_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
880 /* save file first */
881 file_save_as_cmd(after_save_merge_dialog, data);
883 case(ESD_BTN_CANCEL):
886 g_assert_not_reached();
891 file_merge_cmd_cb(GtkWidget *widget, gpointer data _U_) {
894 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
895 /* user didn't saved his current file, ask him */
896 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
897 "%sSave the capture file before merging to another one?%s\n\n"
898 "A temporary capture file can't be merged.",
899 simple_dialog_primary_start(), simple_dialog_primary_end());
900 simple_dialog_set_cb(dialog, file_merge_answered_cb, widget);
902 /* unchanged file, just start to merge */
903 file_merge_cmd(widget);
909 file_merge_ok_cb(GtkWidget *w, gpointer fs) {
911 const gchar *rfilter;
912 GtkWidget *filter_te, *rb;
913 dfilter_t *rfcode = NULL;
915 cf_status_t merge_status;
916 char *in_filenames[2];
919 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
920 filter_te = g_object_get_data(G_OBJECT(w), E_RFILTER_TE_KEY);
921 rfilter = gtk_entry_get_text(GTK_ENTRY(filter_te));
922 if (!dfilter_compile(rfilter, &rfcode)) {
923 bad_dfilter_alert_box(rfilter);
928 /* Perhaps the user specified a directory instead of a file.
929 Check whether they did. */
930 if (test_for_directory(cf_name) == EISDIR) {
931 /* It's a directory - set the file selection box to display that
932 directory, don't try to open the directory as a capture file. */
933 set_last_open_dir(cf_name);
935 file_selection_set_current_folder(fs, get_last_open_dir());
939 /* merge or append the two files */
940 rb = g_object_get_data(G_OBJECT(w), E_MERGE_CHRONO_KEY);
942 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
943 /* chronological order */
944 in_filenames[0] = cfile.filename;
945 in_filenames[1] = cf_name;
946 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype, FALSE);
948 rb = g_object_get_data(G_OBJECT(w), E_MERGE_PREPEND_KEY);
949 if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (rb))) {
951 in_filenames[0] = cf_name;
952 in_filenames[1] = cfile.filename;
953 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype,
957 in_filenames[0] = cfile.filename;
958 in_filenames[1] = cf_name;
959 merge_status = cf_merge_files(&tmpname, 2, in_filenames, filetype,
966 if (merge_status != CF_OK) {
968 dfilter_free(rfcode);
975 /* We've crossed the Rubicon; get rid of the file selection box. */
976 window_destroy(GTK_WIDGET (fs));
978 /* Try to open the merged capture file. */
979 if (cf_open(&cfile, tmpname, TRUE /* temporary file */, &err) != CF_OK) {
980 /* We couldn't open it; don't dismiss the open dialog box,
981 just leave it around so that the user can, after they
982 dismiss the alert box popped up for the open error,
985 dfilter_free(rfcode);
987 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
988 * as this will prevent the user from closing the now existing error
989 * message, simply close the dialog (this is the best we can do here). */
991 window_destroy(file_open_w);
996 /* Attach the new read filter to "cf" ("cf_open()" succeeded, so
997 it closed the previous capture file, and thus destroyed any
998 previous read filter attached to "cf"). */
999 cfile.rfcode = rfcode;
1001 switch (cf_read(&cfile)) {
1005 /* Just because we got an error, that doesn't mean we were unable
1006 to read any of the file; we handle what we could get from the
1010 case CF_READ_ABORTED:
1011 /* The user bailed out of re-reading the capture file; the
1012 capture file has been closed - just free the capture file name
1013 string and return (without changing the last containing
1018 /* Save the name of the containing directory specified in the path name,
1019 if any; we can write over cf_merged_name, which is a good thing, given that
1020 "get_dirname()" does write over its argument. */
1021 s = get_dirname(tmpname);
1022 set_last_open_dir(s);
1023 gtk_widget_grab_focus(packet_list);
1027 file_merge_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1029 /* Note that we no longer have a "Merge Capture File" dialog box. */
1030 file_merge_w = NULL;
1034 static void file_close_answered_cb(gpointer dialog _U_, gint btn, gpointer data _U_)
1038 /* save file first */
1039 file_save_as_cmd(after_save_close_file, NULL);
1041 case(ESD_BTN_DONT_SAVE):
1044 case(ESD_BTN_CANCEL):
1047 g_assert_not_reached();
1053 file_close_cmd_cb(GtkWidget *widget _U_, gpointer data _U_) {
1056 if((cfile.state != FILE_CLOSED) && !cfile.user_saved && prefs.gui_ask_unsaved) {
1057 /* user didn't saved his current file, ask him */
1058 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_SAVE_DONTSAVE_CANCEL,
1059 "%sSave capture file before closing it?%s\n\n"
1060 "If you close without saving, your capture data will be discarded.",
1061 simple_dialog_primary_start(), simple_dialog_primary_end());
1063 simple_dialog_set_cb(dialog, file_close_answered_cb, NULL);
1065 /* unchanged file, just close it */
1071 file_save_cmd_cb(GtkWidget *w, gpointer data) {
1072 /* If the file's already been saved, do nothing. */
1073 if (cfile.user_saved)
1076 /* Do a "Save As". */
1077 file_save_as_cmd_cb(w, data);
1081 can_save_with_wiretap(int ft)
1083 /* To save a file with Wiretap, Wiretap has to handle that format,
1084 and its code to handle that format must be able to write a file
1085 with this file's encapsulation type. */
1086 return wtap_dump_can_open(ft) && wtap_dump_can_write_encap(ft, cfile.lnk_t);
1090 /* Generate a list of the file types we can save this file as, by
1091 checking what Wiretap supports. */
1093 set_file_type_list(GtkWidget *option_menu)
1095 GtkWidget *ft_menu, *ft_menu_item;
1098 gint item_to_select;
1100 /* Default to the first supported file type, if the file's current
1101 type isn't supported. */
1102 item_to_select = -1;
1104 ft_menu = gtk_menu_new();
1106 /* Check all file types. */
1108 for (ft = 0; ft < WTAP_NUM_FILE_TYPES; ft++) {
1109 if (can_save_with_wiretap(ft)) {
1110 /* OK, we can write it out in this type. */
1111 ft_menu_item = gtk_menu_item_new_with_label(wtap_file_type_string(ft));
1112 if (ft == filetype) {
1113 /* Default to the same format as the file, if it's supported. */
1114 item_to_select = index;
1116 g_signal_connect(ft_menu_item, "activate", G_CALLBACK(select_file_type_cb),
1117 GINT_TO_POINTER(ft));
1118 gtk_menu_shell_append(GTK_MENU_SHELL(ft_menu), ft_menu_item);
1119 gtk_widget_show(ft_menu_item);
1124 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), ft_menu);
1125 if (item_to_select >= 0) {
1126 /* Select the current File format in the menu */
1127 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), item_to_select);
1128 select_file_type_cb(NULL, GINT_TO_POINTER(filetype));
1132 * Manually call the signal handler to activate the first menu item
1133 * since gtk_option_menu_set_history() doesn't do it for us. The first two
1134 * entries in the wiretap file types are placeholders so we start at #2, which
1135 * is the normal libpcap format.
1137 gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), 0);
1138 select_file_type_cb(NULL, GINT_TO_POINTER(WTAP_FILE_PCAP));
1143 select_file_type_cb(GtkWidget *w _U_, gpointer data)
1145 int new_filetype = GPOINTER_TO_INT(data);
1146 GtkWidget *compressed_cb;
1148 if (filetype != new_filetype) {
1149 filetype = new_filetype;
1150 compressed_cb = g_object_get_data(G_OBJECT(file_save_as_w), "compressed");
1152 gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(new_filetype));
1158 * Update various dynamic parts of the range controls; called from outside
1159 * the file dialog code whenever the packet counts change.
1162 file_save_update_dynamics(void)
1164 if (file_save_as_w == NULL) {
1165 /* We don't currently have a "Save As..." dialog box up. */
1169 range_update_dynamics(range_tb);
1173 action_after_save_e action_after_save_g;
1174 gpointer action_after_save_data_g;
1178 file_save_as_cmd(action_after_save_e action_after_save, gpointer action_after_save_data)
1181 win32_save_as_file(GDK_WINDOW_HWND(top_level->window), action_after_save, action_after_save_data);
1183 GtkWidget *main_vb, *ft_hb, *ft_lb, *range_fr, *compressed_cb;
1184 GtkTooltips *tooltips;
1186 if (file_save_as_w != NULL) {
1187 /* There's already an "Save Capture File As" dialog box; reactivate it. */
1188 reactivate_window(file_save_as_w);
1192 /* Default to saving all packets, in the file's current format. */
1193 filetype = cfile.cd_t;
1195 /* init the packet range */
1196 packet_range_init(&range);
1198 /* Enable tooltips */
1199 tooltips = gtk_tooltips_new();
1201 /* build the file selection */
1202 file_save_as_w = file_selection_new ("Wireshark: Save Capture File As",
1203 FILE_SELECTION_SAVE);
1205 /* as the dialog might already be gone, when using this values, we cannot
1206 * set data to the dialog object, but keep global values */
1207 action_after_save_g = action_after_save;
1208 action_after_save_data_g = action_after_save_data;
1210 /* Container for each row of widgets */
1212 main_vb = gtk_vbox_new(FALSE, 5);
1213 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1214 file_selection_set_extra_widget(file_save_as_w, main_vb);
1215 gtk_widget_show(main_vb);
1217 /*** Packet Range frame ***/
1218 range_fr = gtk_frame_new("Packet Range");
1219 gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
1220 gtk_widget_show(range_fr);
1223 range_tb = range_new(&range);
1224 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
1225 gtk_widget_show(range_tb);
1228 ft_hb = gtk_hbox_new(FALSE, 3);
1229 gtk_container_add(GTK_CONTAINER(main_vb), ft_hb);
1230 gtk_widget_show(ft_hb);
1232 ft_lb = gtk_label_new("File type:");
1233 gtk_box_pack_start(GTK_BOX(ft_hb), ft_lb, FALSE, FALSE, 0);
1234 gtk_widget_show(ft_lb);
1236 ft_om = gtk_option_menu_new();
1238 /* Generate the list of file types we can save. */
1239 set_file_type_list(ft_om);
1240 gtk_box_pack_start(GTK_BOX(ft_hb), ft_om, FALSE, FALSE, 0);
1241 gtk_widget_show(ft_om);
1243 /* dynamic values in the range frame */
1244 range_update_dynamics(range_tb);
1247 compressed_cb = gtk_check_button_new_with_label("Compress with gzip");
1248 gtk_container_add(GTK_CONTAINER(ft_hb), compressed_cb);
1249 /* XXX - disable output compression for now, as this doesn't work with the
1250 * current optimization to simply copy a capture file if it's using the same
1251 * encapsulation ... */
1252 /* the rest of the implementation is just working fine :-( */
1253 /*gtk_widget_show(compressed_cb);*/
1254 g_object_set_data(G_OBJECT(file_save_as_w), "compressed", compressed_cb);
1255 gtk_widget_set_sensitive(compressed_cb, wtap_dump_can_compress(cfile.cd_t));
1257 g_signal_connect(file_save_as_w, "destroy",
1258 G_CALLBACK(file_save_as_destroy_cb), NULL);
1260 if (gtk_dialog_run(GTK_DIALOG(file_save_as_w)) == GTK_RESPONSE_ACCEPT) {
1261 file_save_as_ok_cb(file_save_as_w, file_save_as_w);
1263 window_destroy(file_save_as_w);
1269 file_save_as_cmd_cb(GtkWidget *w _U_, gpointer data _U_)
1271 file_save_as_cmd(after_save_no_action, NULL);
1275 /* all tests ok, we only have to save the file */
1276 /* (and probably continue with a pending operation) */
1278 file_save_as_cb(GtkWidget *w _U_, gpointer fs) {
1281 GtkWidget *compressed_cb;
1284 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1286 compressed_cb = g_object_get_data(G_OBJECT(file_save_as_w), "compressed");
1288 /* XXX - if the user requests to save to an already existing filename, */
1289 /* ask in a dialog if that's intended */
1290 /* currently, cf_save() will simply deny it */
1292 /* Write out the packets (all, or only the ones from the current
1293 range) to the file with the specified name. */
1294 if (cf_save(&cfile, cf_name, &range, filetype,
1295 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(compressed_cb))) != CF_OK) {
1296 /* The write failed; don't dismiss the open dialog box,
1297 just leave it around so that the user can, after they
1298 dismiss the alert box popped up for the error, try again. */
1300 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1301 * as this will prevent the user from closing the now existing error
1302 * message, simply close the dialog (this is the best we can do here). */
1304 window_destroy(GTK_WIDGET (fs));
1308 /* The write succeeded; get rid of the file selection box. */
1309 /* cf_save() might already closed our dialog! */
1311 window_destroy(GTK_WIDGET (fs));
1313 /* Save the directory name for future file dialogs. */
1314 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1315 set_last_open_dir(dirname);
1318 /* we have finished saving, do we have pending things to do? */
1319 switch(action_after_save_g) {
1320 case(after_save_no_action):
1322 case(after_save_open_dialog):
1323 file_open_cmd(action_after_save_data_g);
1325 case(after_save_open_recent_file):
1326 menu_open_recent_file_cmd(action_after_save_data_g);
1328 case(after_save_open_dnd_file):
1329 dnd_open_file_cmd(action_after_save_data_g);
1331 case(after_save_merge_dialog):
1332 file_merge_cmd(action_after_save_data_g);
1335 case(after_save_capture_dialog):
1336 capture_start_confirmed();
1339 case(after_save_close_file):
1342 case(after_save_exit):
1346 g_assert_not_reached();
1349 action_after_save_g = after_save_no_action;
1353 static void file_save_as_exists_answered_cb(gpointer dialog _U_, gint btn, gpointer data)
1357 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(data));
1363 file_save_as_cb(NULL, data);
1365 case(ESD_BTN_CANCEL):
1366 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1367 * as this will prevent the user from closing the now existing error
1368 * message, simply close the dialog (this is the best we can do here). */
1370 window_destroy(file_save_as_w);
1373 g_assert_not_reached();
1379 /* user pressed "Save" dialog "Ok" button */
1381 file_save_as_ok_cb(GtkWidget *w _U_, gpointer fs) {
1385 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1387 /* Perhaps the user specified a directory instead of a file.
1388 Check whether they did. */
1389 if (test_for_directory(cf_name) == EISDIR) {
1390 /* It's a directory - set the file selection box to display that
1391 directory, and leave the selection box displayed. */
1392 set_last_open_dir(cf_name);
1394 file_selection_set_current_folder(fs, get_last_open_dir());
1398 /* Check whether the range is valid. */
1399 if (!range_check_validity(&range)) {
1400 /* The range isn't valid; don't dismiss the open dialog box,
1401 just leave it around so that the user can, after they
1402 dismiss the alert box popped up for the error, try again. */
1404 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1405 * as this will prevent the user from closing the now existing error
1406 * message, simply close the dialog (this is the best we can do here). */
1408 window_destroy(GTK_WIDGET (fs));
1414 * Check that the from file is not the same as to file
1415 * We do it here so we catch all cases ...
1416 * Unfortunately, the file requester gives us an absolute file
1417 * name and the read file name may be relative (if supplied on
1418 * the command line). From Joerg Mayer.
1420 if (files_identical(cfile.filename, cf_name)) {
1421 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1422 "%sCapture file: \"%s\" identical to loaded file!%s\n\n"
1423 "Please choose a different filename.",
1424 simple_dialog_primary_start(), cf_name, simple_dialog_primary_end());
1426 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1427 * as this will prevent the user from closing the now existing error
1428 * message, simply close the dialog (this is the best we can do here). */
1430 window_destroy(GTK_WIDGET (fs));
1435 /* don't show the dialog while saving (or asking) */
1436 gtk_widget_hide(GTK_WIDGET (fs));
1438 /* it the file doesn't exist, simply try to save it */
1439 if (!file_exists(cf_name)) {
1440 file_save_as_cb(NULL, fs);
1445 /* the file exists, ask the user to remove it first */
1446 dialog = simple_dialog(ESD_TYPE_CONFIRMATION, ESD_BTNS_OK_CANCEL,
1447 "%sA file named \"%s\" already exists.%s\n\n"
1448 "Do you want to replace it with the capture you are saving?",
1449 simple_dialog_primary_start(), cf_name, simple_dialog_primary_end());
1450 simple_dialog_set_cb(dialog, file_save_as_exists_answered_cb, fs);
1456 file_save_as_destroy(void)
1459 window_destroy(file_save_as_w);
1463 file_save_as_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1465 /* Note that we no longer have a "Save Capture File As" dialog box. */
1466 file_save_as_w = NULL;
1469 /* Reload a file using the current read and display filters */
1471 file_reload_cmd_cb(GtkWidget *w _U_, gpointer data _U_) {
1475 /******************** Color Filters *********************************/
1477 * Keep a static pointer to the current "Color Export" window, if
1478 * any, so that if somebody tries to do "Export"
1479 * while there's already a "Color Export" window up, we just pop
1480 * up the existing one, rather than creating a new one.
1482 static GtkWidget *file_color_import_w;
1484 /* sets the file path to the global color filter file.
1485 WARNING: called by both the import and the export dialog.
1488 color_global_cb(GtkWidget *widget _U_, gpointer data)
1490 GtkWidget *fs_widget = data;
1493 /* decide what file to open (from dfilter code) */
1494 path = get_datafile_path("colorfilters");
1496 gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(fs_widget), path);
1498 g_free((gchar *)path);
1501 /* Import color filters */
1503 file_color_import_cmd_cb(GtkWidget *color_filters, gpointer filter_list _U_)
1506 win32_import_color_file(GDK_WINDOW_HWND(top_level->window), color_filters);
1508 GtkWidget *main_vb, *cfglobal_but;
1510 /* No Apply button, and "OK" just sets our text widget, it doesn't
1511 activate it (i.e., it doesn't cause us to try to open the file). */
1513 if (file_color_import_w != NULL) {
1514 /* There's already an "Import Color Filters" dialog box; reactivate it. */
1515 reactivate_window(file_color_import_w);
1519 file_color_import_w = file_selection_new("Wireshark: Import Color Filters",
1520 FILE_SELECTION_OPEN);
1522 /* Container for each row of widgets */
1523 main_vb = gtk_vbox_new(FALSE, 3);
1524 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1525 file_selection_set_extra_widget(file_color_import_w, main_vb);
1526 gtk_widget_show(main_vb);
1529 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1530 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1531 g_signal_connect(cfglobal_but, "clicked",
1532 G_CALLBACK(color_global_cb), file_color_import_w);
1533 gtk_widget_show(cfglobal_but);
1535 g_signal_connect(file_color_import_w, "destroy",
1536 G_CALLBACK(file_color_import_destroy_cb), NULL);
1539 if (gtk_dialog_run(GTK_DIALOG(file_color_import_w)) == GTK_RESPONSE_ACCEPT)
1541 file_color_import_ok_cb(file_color_import_w, color_filters);
1543 else window_destroy(file_color_import_w);
1548 file_color_import_ok_cb(GtkWidget *w, gpointer color_filters) {
1550 GtkWidget *fs = gtk_widget_get_toplevel(w);
1552 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1554 /* Perhaps the user specified a directory instead of a file.
1555 Check whether they did. */
1556 if (test_for_directory(cf_name) == EISDIR) {
1557 /* It's a directory - set the file selection box to display that
1558 directory, don't try to open the directory as a color filter file. */
1559 set_last_open_dir(cf_name);
1561 file_selection_set_current_folder(fs, get_last_open_dir());
1565 /* Try to open the color filter file. */
1567 if (!color_filters_import(cf_name, color_filters)) {
1568 /* We couldn't open it; don't dismiss the open dialog box,
1569 just leave it around so that the user can, after they
1570 dismiss the alert box popped up for the open error,
1573 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1574 * as this will prevent the user from closing the now existing error
1575 * message, simply close the dialog (this is the best we can do here). */
1576 window_destroy(GTK_WIDGET (fs));
1581 /* We've crossed the Rubicon; get rid of the file selection box. */
1582 window_destroy(GTK_WIDGET (fs));
1584 /* Save the name of the containing directory specified in the path name,
1585 if any; we can write over cf_name, which is a good thing, given that
1586 "get_dirname()" does write over its argument. */
1587 s = get_dirname(cf_name);
1588 set_last_open_dir(s);
1589 gtk_widget_grab_focus(packet_list);
1595 file_color_import_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1597 /* Note that we no longer have a "Open Capture File" dialog box. */
1598 file_color_import_w = NULL;
1601 static GtkWidget *file_color_export_w;
1603 * Set the "Export only selected filters" toggle button as appropriate for
1604 * the current output file type and count of selected filters.
1606 * Called when the "Export" dialog box is created and when the selected
1610 color_set_export_selected_sensitive(GtkWidget * cfselect_cb)
1612 if (file_color_export_w == NULL) {
1613 /* We don't currently have an "Export" dialog box up. */
1617 /* We can request that only the selected filters be saved only if
1618 there *are* selected filters. */
1619 if (color_selected_count() != 0)
1620 gtk_widget_set_sensitive(cfselect_cb, TRUE);
1622 /* Force the "Export only selected filters" toggle to "false", turn
1623 off the flag it controls. */
1624 color_selected = FALSE;
1625 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfselect_cb), FALSE);
1626 gtk_widget_set_sensitive(cfselect_cb, FALSE);
1631 color_toggle_selected_cb(GtkWidget *widget, gpointer data _U_)
1633 color_selected = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
1637 file_color_export_cmd_cb(GtkWidget *w _U_, gpointer filter_list)
1640 win32_export_color_file(GDK_WINDOW_HWND(top_level->window), filter_list);
1642 GtkWidget *main_vb, *cfglobal_but;
1644 if (file_color_export_w != NULL) {
1645 /* There's already an "Color Filter Export" dialog box; reactivate it. */
1646 reactivate_window(file_color_export_w);
1650 color_selected = FALSE;
1652 file_color_export_w = file_selection_new("Wireshark: Export Color Filters",
1653 FILE_SELECTION_SAVE);
1655 /* Container for each row of widgets */
1656 main_vb = gtk_vbox_new(FALSE, 3);
1657 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
1658 file_selection_set_extra_widget(file_color_export_w, main_vb);
1659 gtk_widget_show(main_vb);
1661 cfselect_cb = gtk_check_button_new_with_label("Export only selected filters");
1662 gtk_container_add(GTK_CONTAINER(main_vb), cfselect_cb);
1663 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cfselect_cb), FALSE);
1664 g_signal_connect(cfselect_cb, "toggled",
1665 G_CALLBACK(color_toggle_selected_cb), NULL);
1666 gtk_widget_show(cfselect_cb);
1667 color_set_export_selected_sensitive(cfselect_cb);
1669 cfglobal_but = gtk_button_new_with_label("Global Color Filter File");
1670 gtk_container_add(GTK_CONTAINER(main_vb), cfglobal_but);
1671 g_signal_connect(cfglobal_but, "clicked",
1672 G_CALLBACK(color_global_cb), file_color_export_w);
1673 gtk_widget_show(cfglobal_but);
1675 g_signal_connect(file_color_export_w, "destroy",
1676 G_CALLBACK(file_color_export_destroy_cb), NULL);
1678 if (gtk_dialog_run(GTK_DIALOG(file_color_export_w)) == GTK_RESPONSE_ACCEPT)
1680 file_color_export_ok_cb(file_color_export_w, filter_list);
1682 else window_destroy(file_color_export_w);
1687 file_color_export_ok_cb(GtkWidget *w, gpointer filter_list) {
1690 GtkWidget *fs = gtk_widget_get_toplevel(w);
1692 cf_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));
1694 /* Perhaps the user specified a directory instead of a file.
1695 Check whether they did. */
1696 if (test_for_directory(cf_name) == EISDIR) {
1697 /* It's a directory - set the file selection box to display that
1698 directory, and leave the selection box displayed. */
1699 set_last_open_dir(cf_name);
1701 file_selection_set_current_folder(fs, get_last_open_dir());
1705 /* Write out the filters (all, or only the ones that are currently
1706 displayed or selected) to the file with the specified name. */
1708 if (!color_filters_export(cf_name, filter_list, color_selected))
1710 /* The write failed; don't dismiss the open dialog box,
1711 just leave it around so that the user can, after they
1712 dismiss the alert box popped up for the error, try again. */
1715 /* XXX - as we cannot start a new event loop (using gtk_dialog_run()),
1716 * as this will prevent the user from closing the now existing error
1717 * message, simply close the dialog (this is the best we can do here). */
1718 window_destroy(GTK_WIDGET (fs));
1723 /* The write succeeded; get rid of the file selection box. */
1724 window_destroy(GTK_WIDGET (fs));
1726 /* Save the directory name for future file dialogs. */
1727 dirname = get_dirname(cf_name); /* Overwrites cf_name */
1728 set_last_open_dir(dirname);
1733 file_color_export_destroy_cb(GtkWidget *win _U_, gpointer user_data _U_)
1735 file_color_export_w = NULL;