2 * Dialog boxes for printing and exporting to text 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.
34 #include "gtkglobals.h"
37 #include <epan/prefs.h>
38 #include "alert_box.h"
39 #include "simple_dialog.h"
40 #include "capture_file_dlg.h"
41 #include "gui_utils.h"
42 #include "dlg_utils.h"
45 #include <epan/epan_dissect.h>
46 #include <epan/filesystem.h>
48 #include "print_mswin.h"
50 #include "compat_macros.h"
51 #include "range_utils.h"
53 #include "file_util.h"
58 #include <gdk/gdkwin32.h>
60 #include "win32-file-dlg.h"
63 /* dialog output action */
65 output_action_print, /* print text to printer */
66 output_action_export_text, /* export to plain text */
67 output_action_export_ps, /* export to postscript */
68 output_action_export_psml, /* export to packet summary markup language */
69 output_action_export_pdml, /* export to packet data markup language */
70 output_action_export_csv, /* export to csv file */
71 output_action_export_carrays /* export to C array file */
75 /* On Win32, a GUI application apparently can't use "popen()" (it
76 "returns an invalid file handle, if used in a Windows program,
77 that will cause the program to hang indefinitely"), so we can't
78 use a pipe to a print command to print to a printer.
80 Eventually, we should try to use the native Win32 printing API
81 for this (and also use various UNIX printing APIs, when present?).
85 open_print_dialog(const char *title, output_action_e action, print_args_t *args);
86 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
87 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
88 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
89 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
93 #define PRINT_ARGS_KEY "printer_args"
95 #define PRINT_PS_RB_KEY "printer_ps_radio_button"
96 #define PRINT_PDML_RB_KEY "printer_pdml_radio_button"
97 #define PRINT_PSML_RB_KEY "printer_psml_radio_button"
98 #define PRINT_CSV_RB_KEY "printer_csv_radio_button"
99 #define PRINT_CARRAYS_RB_KEY "printer_carrays_radio_button"
100 #define PRINT_DEST_CB_KEY "printer_destination_check_button"
102 #define PRINT_SUMMARY_CB_KEY "printer_summary_check_button"
103 #define PRINT_DETAILS_CB_KEY "printer_details_check_button"
104 #define PRINT_COLLAPSE_ALL_RB_KEY "printer_collapse_all_radio_button"
105 #define PRINT_AS_DISPLAYED_RB_KEY "printer_as_displayed_radio_button"
106 #define PRINT_EXPAND_ALL_RB_KEY "printer_expand_all_radio_button"
107 #define PRINT_HEX_CB_KEY "printer_hex_check_button"
108 #define PRINT_FORMFEED_CB_KEY "printer_formfeed_check_button"
110 #define PRINT_BT_KEY "printer_button"
112 #define PRINT_TE_PTR_KEY "printer_file_te_ptr"
116 * Keep a static pointer to the current "Print" window, if any, so that if
117 * somebody tries to do "File:Print" while there's already a "Print" window
118 * up, we just pop up the existing one, rather than creating a new one.
120 static GtkWidget *print_win = NULL;
122 static print_args_t print_args;
124 static gboolean print_prefs_init = FALSE;
128 file_print_cmd(gboolean print_selected)
130 print_args_t *args = &print_args;
132 if (print_win != NULL) {
133 /* There's already a "Print" dialog box; reactivate it. */
134 reactivate_window(print_win);
138 /* get settings from preferences (and other initial values) only once */
139 if(print_prefs_init == FALSE) {
140 print_prefs_init = TRUE;
141 args->format = prefs.pr_format;
142 args->to_file = prefs.pr_dest;
143 args->file = g_strdup(prefs.pr_file);
144 args->cmd = g_strdup(prefs.pr_cmd);
145 args->print_summary = TRUE;
146 args->print_dissections = print_dissections_as_displayed;
147 args->print_hex = FALSE;
148 args->print_formfeed = FALSE;
151 /* init the printing range */
152 packet_range_init(&args->range);
155 args->range.process = range_process_selected;
158 print_win = open_print_dialog("Wireshark: Print", output_action_print, args);
159 SIGNAL_CONNECT(print_win, "destroy", print_destroy_cb, &print_win);
163 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
165 file_print_cmd(FALSE);
169 file_print_selected_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
171 file_print_cmd(TRUE);
175 * Keep a static pointer to the current "Export text" window, if any, so that if
176 * somebody tries to do "File:Export to text" while there's already a "Export text" window
177 * up, we just pop up the existing one, rather than creating a new one.
179 static GtkWidget *export_text_win = NULL;
181 static print_args_t export_text_args;
183 static gboolean export_text_prefs_init = FALSE;
187 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
189 print_args_t *args = &export_text_args;
192 win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_text);
196 if (export_text_win != NULL) {
197 /* There's already a "Export text" dialog box; reactivate it. */
198 reactivate_window(export_text_win);
202 /* get settings from preferences (and other initial values) only once */
203 if(export_text_prefs_init == FALSE) {
204 export_text_prefs_init = TRUE;
205 args->format = PR_FMT_TEXT;
206 args->to_file = TRUE;
207 args->file = g_strdup("");
208 args->cmd = g_strdup("");
209 args->print_summary = TRUE;
210 args->print_dissections = print_dissections_as_displayed;
211 args->print_hex = FALSE;
212 args->print_formfeed = FALSE;
215 /* init the printing range */
216 packet_range_init(&args->range);
218 export_text_win = open_print_dialog("Wireshark: Export as \"Plain Text\" File", output_action_export_text, args);
219 SIGNAL_CONNECT(export_text_win, "destroy", print_destroy_cb, &export_text_win);
224 * Keep a static pointer to the current "Export ps" window, if any, so that if
225 * somebody tries to do "File:Export to ps" while there's already a "Export ps" window
226 * up, we just pop up the existing one, rather than creating a new one.
228 static GtkWidget *export_ps_win = NULL;
230 static print_args_t export_ps_args;
232 static gboolean export_ps_prefs_init = FALSE;
236 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
238 print_args_t *args = &export_ps_args;
241 win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_ps);
245 if (export_ps_win != NULL) {
246 /* There's already a "Export ps" dialog box; reactivate it. */
247 reactivate_window(export_ps_win);
251 /* get settings from preferences (and other initial values) only once */
252 if(export_ps_prefs_init == FALSE) {
253 export_ps_prefs_init = TRUE;
254 args->format = PR_FMT_PS;
255 args->to_file = TRUE;
256 args->file = g_strdup("");
257 args->cmd = g_strdup("");
258 args->print_summary = TRUE;
259 args->print_dissections = print_dissections_as_displayed;
260 args->print_hex = FALSE;
261 args->print_formfeed = FALSE;
264 /* init the printing range */
265 packet_range_init(&args->range);
267 export_ps_win = open_print_dialog("Wireshark: Export as \"PostScript\" file", output_action_export_ps, args);
268 SIGNAL_CONNECT(export_ps_win, "destroy", print_destroy_cb, &export_ps_win);
273 * Keep a static pointer to the current "Export psml" window, if any, so that if
274 * somebody tries to do "File:Export to psml" while there's already a "Export psml" window
275 * up, we just pop up the existing one, rather than creating a new one.
277 static GtkWidget *export_psml_win = NULL;
279 static print_args_t export_psml_args;
281 static gboolean export_psml_prefs_init = FALSE;
285 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
287 print_args_t *args = &export_psml_args;
290 win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_psml);
294 if (export_psml_win != NULL) {
295 /* There's already a "Export psml" dialog box; reactivate it. */
296 reactivate_window(export_psml_win);
300 /* get settings from preferences (and other initial values) only once */
301 if(export_psml_prefs_init == FALSE) {
302 export_psml_prefs_init = TRUE;
303 args->format = PR_FMT_TEXT; /* XXX */
304 args->to_file = TRUE;
305 args->file = g_strdup("");
306 args->cmd = g_strdup("");
307 args->print_summary = TRUE;
308 args->print_dissections = print_dissections_as_displayed;
309 args->print_hex = FALSE;
310 args->print_formfeed = FALSE;
313 /* init the printing range */
314 packet_range_init(&args->range);
316 export_psml_win = open_print_dialog("Wireshark: Export as \"PSML\" file", output_action_export_psml, args);
317 SIGNAL_CONNECT(export_psml_win, "destroy", print_destroy_cb, &export_psml_win);
322 * Keep a static pointer to the current "Export pdml" window, if any, so that if
323 * somebody tries to do "File:Export to pdml" while there's already a "Export pdml" window
324 * up, we just pop up the existing one, rather than creating a new one.
326 static GtkWidget *export_pdml_win = NULL;
328 static print_args_t export_pdml_args;
330 static gboolean export_pdml_prefs_init = FALSE;
334 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
336 print_args_t *args = &export_pdml_args;
339 win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_pdml);
343 if (export_pdml_win != NULL) {
344 /* There's already a "Export pdml" dialog box; reactivate it. */
345 reactivate_window(export_pdml_win);
349 /* get settings from preferences (and other initial values) only once */
350 if(export_pdml_prefs_init == FALSE) {
351 export_pdml_prefs_init = TRUE;
352 args->format = PR_FMT_TEXT; /* XXX */
353 args->to_file = TRUE;
354 args->file = g_strdup("");
355 args->cmd = g_strdup("");
356 args->print_summary = TRUE;
357 args->print_dissections = print_dissections_as_displayed;
358 args->print_hex = FALSE;
359 args->print_formfeed = FALSE;
362 /* init the printing range */
363 packet_range_init(&args->range);
365 export_pdml_win = open_print_dialog("Wireshark: Export as \"PDML\" file", output_action_export_pdml, args);
366 SIGNAL_CONNECT(export_pdml_win, "destroy", print_destroy_cb, &export_pdml_win);
370 * Keep a static pointer to the current "Export csv" window, if any, so that if
371 * somebody tries to do "File:Export to CSV" while there's already a "Export csv" window
372 * up, we just pop up the existing one, rather than creating a new one.
374 static GtkWidget *export_csv_win = NULL;
376 static print_args_t export_csv_args;
378 static gboolean export_csv_prefs_init = FALSE;
381 export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
383 print_args_t *args = &export_csv_args;
386 win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_csv);
390 if (export_csv_win != NULL) {
391 /* There's already a "Export csv" dialog box; reactivate it. */
392 reactivate_window(export_csv_win);
396 /* get settings from preferences (and other initial values) only once */
397 if(export_csv_prefs_init == FALSE) {
398 export_csv_prefs_init = TRUE;
399 args->format = PR_FMT_TEXT; /* XXX */
400 args->to_file = TRUE;
401 args->file = g_strdup("");
402 args->cmd = g_strdup("");
403 args->print_summary = FALSE;
404 args->print_dissections = print_dissections_none;
405 args->print_hex = FALSE;
406 args->print_formfeed = FALSE;
409 /* init the printing range */
410 packet_range_init(&args->range);
412 export_csv_win = open_print_dialog("Wireshark: Export as \"Comma Separated Values\" File", output_action_export_csv, args);
413 SIGNAL_CONNECT(export_csv_win, "destroy", print_destroy_cb, &export_csv_win);
417 * Keep a static pointer to the current "Export carrays" window, if any, so that if
418 * somebody tries to do "File:Export to carrays" while there's already a "Export carrays" window
419 * up, we just pop up the existing one, rather than creating a new one.
421 static GtkWidget *export_carrays_win = NULL;
423 static print_args_t export_carrays_args;
425 static gboolean export_carrays_prefs_init = FALSE;
428 export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
430 print_args_t *args = &export_carrays_args;
433 win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_carrays);
437 if (export_carrays_win != NULL) {
438 /* There's already a "Export carrays" dialog box; reactivate it. */
439 reactivate_window(export_carrays_win);
443 /* get settings from preferences (and other initial values) only once */
444 if(export_carrays_prefs_init == FALSE) {
445 export_carrays_prefs_init = TRUE;
446 args->format = PR_FMT_TEXT;
447 args->to_file = TRUE;
448 args->file = g_strdup("");
449 args->cmd = g_strdup("");
450 args->print_summary = FALSE;
451 args->print_dissections = print_dissections_none;
452 args->print_hex = FALSE;
453 args->print_formfeed = FALSE;
456 /* init the printing range */
457 packet_range_init(&args->range);
459 export_carrays_win = open_print_dialog("Wireshark: Export as \"C Arrays\" File",
460 output_action_export_carrays, args);
461 SIGNAL_CONNECT(export_carrays_win, "destroy", print_destroy_cb, &export_carrays_win);
465 print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
467 file_selection_browse(file_bt, file_te, "Wireshark: Print to File",
468 FILE_SELECTION_WRITE_BROWSE);
473 /* Open the print dialog */
475 open_print_dialog(const char *title, output_action_e action, print_args_t *args)
480 GtkWidget *printer_fr, *printer_vb, *export_format_lb;
481 GtkWidget *text_rb, *ps_rb, *pdml_rb, *psml_rb, *csv_rb, *carrays_rb;
482 GtkWidget *printer_tb, *dest_cb;
484 GtkWidget *cmd_lb, *cmd_te;
486 GtkWidget *file_bt, *file_te;
488 GtkWidget *range_fr, *range_tb;
490 GtkWidget *packet_hb;
492 GtkWidget *format_fr, *format_vb;
493 GtkWidget *summary_cb;
495 GtkWidget *details_cb;
496 GtkWidget *details_hb, *details_vb;
497 GtkWidget *collapse_all_rb, *as_displayed_rb, *expand_all_rb;
499 GtkWidget *sep, *formfeed_cb;
501 GtkWidget *bbox, *ok_bt, *cancel_bt, *help_bt;
503 GtkTooltips *tooltips;
507 main_win = dlg_window_new(title);
509 /* Enable tooltips */
510 tooltips = gtk_tooltips_new();
512 /* Vertical enclosing container for each row of widgets */
513 main_vb = gtk_vbox_new(FALSE, 5);
514 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
515 gtk_container_add(GTK_CONTAINER(main_win), main_vb);
516 gtk_widget_show(main_vb);
518 /*****************************************************/
520 /*** printer frame ***/
521 printer_fr = gtk_frame_new(action == output_action_print ? "Printer" : "Export to file:");
522 gtk_box_pack_start(GTK_BOX(main_vb), printer_fr, FALSE, FALSE, 0);
523 gtk_widget_show(printer_fr);
524 printer_vb = gtk_vbox_new(FALSE, 5);
525 gtk_container_border_width(GTK_CONTAINER(printer_vb), 5);
526 gtk_container_add(GTK_CONTAINER(printer_fr), printer_vb);
527 gtk_widget_show(printer_vb);
529 /* "Plain text" / "Postscript" / "PDML", ... radio buttons */
530 text_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "Plain _text", accel_group);
531 if (args->format == PR_FMT_TEXT)
532 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(text_rb), TRUE);
533 gtk_tooltips_set_tip (tooltips, text_rb, "Print output in ascii \"plain text\" format. If you're unsure, use this format.", NULL);
534 gtk_box_pack_start(GTK_BOX(printer_vb), text_rb, FALSE, FALSE, 0);
535 if(action == output_action_print)
536 gtk_widget_show(text_rb);
538 ps_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "_PostScript", accel_group);
539 if (args->format == PR_FMT_PS)
540 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ps_rb), TRUE);
541 gtk_tooltips_set_tip (tooltips, ps_rb, "Print output in \"postscript\" format, for postscript capable printers or print servers.", NULL);
542 gtk_box_pack_start(GTK_BOX(printer_vb), ps_rb, FALSE, FALSE, 0);
543 if(action == output_action_print)
544 gtk_widget_show(ps_rb);
546 pdml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PDM_L (XML: Packet Details Markup Language)", accel_group);
547 if (action == output_action_export_pdml)
548 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(pdml_rb), TRUE);
549 gtk_tooltips_set_tip (tooltips, pdml_rb,
550 "Print output in \"PDML\" (Packet Details Markup Language), "
551 "an XML based packet data interchange format. "
552 "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.", NULL);
553 gtk_box_pack_start(GTK_BOX(printer_vb), pdml_rb, FALSE, FALSE, 0);
554 /* gtk_widget_show(pdml_rb); */
556 psml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PSML (XML: Packet Summary Markup Language)", accel_group);
557 if (action == output_action_export_psml)
558 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(psml_rb), TRUE);
559 gtk_tooltips_set_tip (tooltips, psml_rb,
560 "Print output in \"PSML\" (Packet Summary Markup Language), "
561 "an XML based packet summary interchange format. "
562 "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.", NULL);
563 gtk_box_pack_start(GTK_BOX(printer_vb), psml_rb, FALSE, FALSE, 0);
564 /* gtk_widget_show(psml_rb); */
566 csv_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "_CSV", accel_group);
567 if (action == output_action_export_csv)
568 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(csv_rb), TRUE);
569 gtk_tooltips_set_tip (tooltips, csv_rb,
570 "Print output in \"Comma Separated Values\" (CSV) format, "
571 "a text format compatible with OpenOffice and Excel. "
572 "One row for each packet, with its timestamp and size.", NULL);
573 gtk_box_pack_start(GTK_BOX(printer_vb), csv_rb, FALSE, FALSE, 0);
574 /* gtk_widget_show(csv_rb); */
576 carrays_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "C Arrays", accel_group);
577 if (action == output_action_export_carrays)
578 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(carrays_rb), TRUE);
579 gtk_tooltips_set_tip (tooltips, carrays_rb,
580 "Print output in C Arrays format, "
581 "a text file suitable for use in C/C++ programs. "
582 "One char[] for each packet.", NULL);
583 gtk_box_pack_start(GTK_BOX(printer_vb), carrays_rb, FALSE, FALSE, 0);
584 /* gtk_widget_show(carrays_rb); */
588 printer_tb = gtk_table_new(2, 3, FALSE);
590 printer_tb = gtk_table_new(2, 2, FALSE);
592 gtk_box_pack_start(GTK_BOX(printer_vb), printer_tb, FALSE, FALSE, 0);
593 gtk_table_set_row_spacings(GTK_TABLE(printer_tb), 5);
594 gtk_table_set_col_spacings(GTK_TABLE(printer_tb), 5);
595 gtk_widget_show(printer_tb);
598 /* Output to file button */
599 dest_cb = gtk_check_button_new_with_mnemonic("Output to _file:");
601 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
602 gtk_tooltips_set_tip (tooltips, dest_cb, "Output to file instead of printer", NULL);
603 gtk_table_attach_defaults(GTK_TABLE(printer_tb), dest_cb, 0, 1, 0, 1);
604 if(action == output_action_print)
605 gtk_widget_show(dest_cb);
607 /* File text entry */
608 file_te = gtk_entry_new();
609 g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_TE_KEY, file_te);
610 gtk_tooltips_set_tip (tooltips, file_te, "Enter Output filename", NULL);
611 gtk_entry_set_text(GTK_ENTRY(file_te), args->file);
612 gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_te, 1, 2, 0, 1);
613 gtk_widget_set_sensitive(file_te, args->to_file);
614 gtk_widget_show(file_te);
616 gtk_widget_grab_focus(file_te);
618 /* "Browse" button */
619 file_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
620 g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_BT_KEY, file_bt);
621 g_object_set_data(G_OBJECT(file_bt), PRINT_TE_PTR_KEY, file_te);
622 gtk_tooltips_set_tip (tooltips, file_bt, "Browse output filename in filesystem", NULL);
623 gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_bt, 2, 3, 0, 1);
624 gtk_widget_set_sensitive(file_bt, args->to_file);
625 gtk_widget_show(file_bt);
627 /* Command label and text entry */
629 cmd_lb = gtk_label_new("Print command:");
630 g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_LB_KEY, cmd_lb);
631 gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
632 gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_lb, 0, 1, 1, 2);
633 gtk_widget_set_sensitive(cmd_lb, !args->to_file);
634 if(action == output_action_print)
635 gtk_widget_show(cmd_lb);
637 cmd_te = gtk_entry_new();
638 g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_TE_KEY, cmd_te);
639 gtk_tooltips_set_tip (tooltips, cmd_te, "Enter print command", NULL);
640 gtk_entry_set_text(GTK_ENTRY(cmd_te), args->cmd);
641 gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_te, 1, 2, 1, 2);
642 gtk_widget_set_sensitive(cmd_te, !args->to_file);
643 if(action == output_action_print)
644 gtk_widget_show(cmd_te);
647 SIGNAL_CONNECT(dest_cb, "toggled", print_cmd_toggle_dest, NULL);
648 SIGNAL_CONNECT(file_bt, "clicked", print_browse_file_cb, file_te);
650 if(action == output_action_export_ps) {
651 export_format_lb = gtk_label_new("(PostScript files can be easily converted to PDF files using ghostscript's ps2pdf)");
652 gtk_box_pack_start(GTK_BOX(printer_vb), export_format_lb, FALSE, FALSE, 0);
653 gtk_widget_show(export_format_lb);
656 /*****************************************************/
658 /*** hor box for range and format frames ***/
659 packet_hb = gtk_hbox_new(FALSE, 5);
660 gtk_container_add(GTK_CONTAINER(main_vb), packet_hb);
661 gtk_widget_show(packet_hb);
663 /*** packet range frame ***/
664 range_fr = gtk_frame_new("Packet Range");
665 gtk_box_pack_start(GTK_BOX(packet_hb), range_fr, FALSE, FALSE, 0);
666 gtk_widget_show(range_fr);
668 range_tb = range_new(&args->range);
669 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
670 gtk_widget_show(range_tb);
672 /*****************************************************/
674 /*** packet format frame ***/
675 format_fr = gtk_frame_new("Packet Format");
676 gtk_box_pack_start(GTK_BOX(packet_hb), format_fr, TRUE, TRUE, 0);
677 if( action == output_action_print ||
678 action == output_action_export_text ||
679 action == output_action_export_ps)
680 gtk_widget_show(format_fr);
681 format_vb = gtk_vbox_new(FALSE, 5);
682 gtk_container_border_width(GTK_CONTAINER(format_vb), 5);
683 gtk_container_add(GTK_CONTAINER(format_fr), format_vb);
684 gtk_widget_show(format_vb);
686 /* "Print summary line" check button */
687 summary_cb = gtk_check_button_new_with_mnemonic("Packet summary line");
688 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(summary_cb), args->print_summary);
689 SIGNAL_CONNECT(summary_cb, "clicked", print_cmd_toggle_detail, main_win);
690 gtk_tooltips_set_tip (tooltips, summary_cb, "Output of a packet summary line, like in the packet list", NULL);
691 gtk_container_add(GTK_CONTAINER(format_vb), summary_cb);
692 gtk_widget_show(summary_cb);
695 /* "Details" check button */
696 details_cb = gtk_check_button_new_with_mnemonic("Packet details:");
697 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(details_cb), args->print_dissections != print_dissections_none);
698 SIGNAL_CONNECT(details_cb, "clicked", print_cmd_toggle_detail, main_win);
699 gtk_tooltips_set_tip (tooltips, details_cb, "Output format of the selected packet details (protocol tree).", NULL);
700 gtk_container_add(GTK_CONTAINER(format_vb), details_cb);
701 gtk_widget_show(details_cb);
703 /*** packet details ***/
704 details_hb = gtk_hbox_new(FALSE, 6);
705 gtk_container_border_width(GTK_CONTAINER(details_hb), 0);
706 gtk_container_add(GTK_CONTAINER(format_vb), details_hb);
707 gtk_widget_show(details_hb);
709 details_vb = gtk_vbox_new(FALSE, 6);
710 gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
711 gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
712 gtk_widget_show(details_vb);
714 details_vb = gtk_vbox_new(FALSE, 6);
715 gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
716 gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
717 gtk_widget_show(details_vb);
719 /* "All collapsed"/"As displayed"/"All Expanded" radio buttons */
720 collapse_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "All co_llapsed", accel_group);
721 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(collapse_all_rb), args->print_dissections == print_dissections_collapsed);
722 gtk_tooltips_set_tip (tooltips, collapse_all_rb, "Output of the packet details tree \"collapsed\"", NULL);
723 gtk_container_add(GTK_CONTAINER(details_vb), collapse_all_rb);
724 gtk_widget_show(collapse_all_rb);
726 as_displayed_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "As displa_yed", accel_group);
727 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(as_displayed_rb), args->print_dissections == print_dissections_as_displayed);
728 gtk_tooltips_set_tip (tooltips, as_displayed_rb, "Output of the packet details tree \"as displayed\"", NULL);
729 gtk_container_add(GTK_CONTAINER(details_vb), as_displayed_rb);
730 gtk_widget_show(as_displayed_rb);
732 expand_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "All e_xpanded", accel_group);
733 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(expand_all_rb), args->print_dissections == print_dissections_expanded);
734 gtk_tooltips_set_tip (tooltips, expand_all_rb, "Output of the packet details tree \"expanded\"", NULL);
735 gtk_container_add(GTK_CONTAINER(details_vb), expand_all_rb);
736 gtk_widget_show(expand_all_rb);
738 /* "Print hex" check button. */
739 hex_cb = gtk_check_button_new_with_mnemonic("Packet bytes");
740 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_cb), args->print_hex);
741 SIGNAL_CONNECT(hex_cb, "clicked", print_cmd_toggle_detail, main_win);
742 gtk_tooltips_set_tip (tooltips, hex_cb, "Add a hexdump of the packet data", NULL);
743 gtk_container_add(GTK_CONTAINER(format_vb), hex_cb);
744 gtk_widget_show(hex_cb);
747 sep = gtk_hseparator_new();
748 gtk_container_add(GTK_CONTAINER(format_vb), sep);
749 gtk_widget_show(sep);
751 /* "Each packet on a new page" check button. */
752 formfeed_cb = gtk_check_button_new_with_mnemonic("Each packet on a new page");
753 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(formfeed_cb), args->print_formfeed);
754 gtk_tooltips_set_tip (tooltips, formfeed_cb, "When checked, a new page will be used for each packet. "
755 "This is done by adding a formfeed (or similar) between the packet outputs.", NULL);
756 gtk_container_add(GTK_CONTAINER(format_vb), formfeed_cb);
757 gtk_widget_show(formfeed_cb);
760 g_object_set_data(G_OBJECT(main_win), PRINT_ARGS_KEY, args);
761 g_object_set_data(G_OBJECT(main_win), PRINT_SUMMARY_CB_KEY, summary_cb);
762 g_object_set_data(G_OBJECT(main_win), PRINT_DETAILS_CB_KEY, details_cb);
763 g_object_set_data(G_OBJECT(main_win), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
764 g_object_set_data(G_OBJECT(main_win), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
765 g_object_set_data(G_OBJECT(main_win), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
766 g_object_set_data(G_OBJECT(main_win), PRINT_HEX_CB_KEY, hex_cb);
768 /*****************************************************/
772 if(topic_available(HELP_PRINT_DIALOG)) {
773 bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
775 bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL);
777 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
778 gtk_widget_show(bbox);
780 ok_bt = g_object_get_data(G_OBJECT(bbox), action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK);
782 g_object_set_data(G_OBJECT(main_win), PRINT_BT_KEY, ok_bt);
784 g_object_set_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY, ps_rb);
785 g_object_set_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY, pdml_rb);
786 g_object_set_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY, psml_rb);
787 g_object_set_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY, csv_rb);
788 g_object_set_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY, carrays_rb);
789 g_object_set_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY, dest_cb);
791 g_object_set_data(G_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
794 g_object_set_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY, args);
795 g_object_set_data(G_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
796 g_object_set_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY, summary_cb);
797 g_object_set_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY, details_cb);
798 g_object_set_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
799 g_object_set_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
800 g_object_set_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
801 g_object_set_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY, hex_cb);
802 g_object_set_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY, formfeed_cb);
803 SIGNAL_CONNECT(ok_bt, "clicked", print_ok_cb, main_win);
804 gtk_tooltips_set_tip (tooltips, ok_bt, "Start output", NULL);
806 cancel_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
807 window_set_cancel_button(main_win, cancel_bt, window_cancel_button_cb);
808 gtk_tooltips_set_tip (tooltips, cancel_bt, "Cancel and exit dialog", NULL);
810 if(action == output_action_print) {
811 if(topic_available(HELP_PRINT_DIALOG)) {
812 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
813 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_PRINT_DIALOG);
817 if(topic_available(HELP_EXPORT_FILE_WIN32_DIALOG)) {
818 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
819 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_EXPORT_FILE_WIN32_DIALOG);
822 if(topic_available(HELP_EXPORT_FILE_DIALOG)) {
823 help_bt = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
824 SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_EXPORT_FILE_DIALOG);
829 gtk_widget_grab_default(ok_bt);
831 /* Catch the "activate" signal on the "Command" and "File" text entries,
832 so that if the user types Return there, we act as if the "OK" button
833 had been selected, as happens if Return is typed if some widget
834 that *doesn't* handle the Return key has the input focus. */
836 dlg_set_activate(cmd_te, ok_bt);
838 if(action != output_action_print)
839 dlg_set_activate(file_te, ok_bt);
841 SIGNAL_CONNECT(main_win, "delete_event", window_delete_event_cb, NULL);
843 gtk_widget_show(main_win);
844 window_present(main_win);
850 /* user changed "print to" destination */
852 print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
855 GtkWidget *cmd_lb, *cmd_te;
857 GtkWidget *file_bt, *file_te;
861 cmd_lb = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_LB_KEY));
862 cmd_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_TE_KEY));
864 file_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_BT_KEY));
865 file_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_TE_KEY));
867 to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
869 gtk_widget_set_sensitive(cmd_lb, !to_file);
870 gtk_widget_set_sensitive(cmd_te, !to_file);
872 gtk_widget_set_sensitive(file_bt, to_file);
873 gtk_widget_set_sensitive(file_te, to_file);
877 /* user changed "packet details" */
879 print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
881 GtkWidget *print_bt, *summary_cb, *details_cb, *collapse_all_rb, *expand_all_rb, *as_displayed_rb, *hex_cb;
882 gboolean print_detail;
885 print_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_BT_KEY));
886 summary_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_SUMMARY_CB_KEY));
887 details_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_DETAILS_CB_KEY));
888 collapse_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_COLLAPSE_ALL_RB_KEY));
889 as_displayed_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_AS_DISPLAYED_RB_KEY));
890 expand_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_EXPAND_ALL_RB_KEY));
891 hex_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_HEX_CB_KEY));
893 /* is user disabled details, disable the corresponding buttons */
894 print_detail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb));
895 gtk_widget_set_sensitive(collapse_all_rb, print_detail);
896 gtk_widget_set_sensitive(as_displayed_rb, print_detail);
897 gtk_widget_set_sensitive(expand_all_rb, print_detail);
899 /* if user selected nothing to print at all, disable the "ok" button */
900 gtk_widget_set_sensitive(print_bt,
901 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (summary_cb)) ||
902 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb)) ||
903 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_cb)));
908 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
915 gboolean export_as_pdml = FALSE, export_as_psml = FALSE;
916 gboolean export_as_csv = FALSE;
917 gboolean export_as_carrays = FALSE;
919 gboolean win_printer = FALSE;
921 char tmp_namebuf[128+1]; /* XXX - length was used elsewhere too, why? */
924 cf_print_status_t status;
926 args = (print_args_t *)g_object_get_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY);
928 /* Check whether the range is valid. */
929 if (!range_check_validity(&args->range)) {
930 /* The range isn't valid; don't dismiss the print/export dialog box,
931 just leave it around so that the user can, after they
932 dismiss the alert box popped up for the error, try again. */
936 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY);
937 args->to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
940 g_dest = gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
941 PRINT_FILE_TE_KEY)));
943 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
944 "Output to file, but no file specified.");
948 args->file = g_strdup(g_dest);
949 /* Save the directory name for future file dialogs. */
950 f_name = g_strdup(g_dest);
951 dirname = get_dirname(f_name); /* Overwrites f_name */
952 set_last_open_dir(dirname);
957 /* We currently don't have a function in util.h to create just a tempfile */
958 /* name, so simply create a tempfile using the "official" function, */
959 /* then delete this file again. After this, the name MUST be available. */
961 /* Don't use tmpnam() or such, as this will fail under some ACL */
962 /* circumstances: http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=358 */
964 tmp_fd = create_tempfile(tmp_namebuf, sizeof(tmp_namebuf), "ethprint");
966 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
967 "Couldn't create a temporary file for printing.");
970 /* remember to restore these values later! */
971 tmp_oldfile = args->file;
972 args->file = g_strdup(tmp_namebuf);
973 eth_unlink(args->file);
974 args->to_file = TRUE;
977 args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
978 PRINT_CMD_TE_KEY))));
982 args->format = PR_FMT_TEXT;
983 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY);
984 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
985 args->format = PR_FMT_PS;
986 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY);
987 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
988 export_as_pdml = TRUE;
989 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY);
990 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
991 export_as_psml = TRUE;
992 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY);
993 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
994 export_as_csv = TRUE;
995 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY);
996 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
997 export_as_carrays = TRUE;
999 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY);
1000 args->print_summary = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1002 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY);
1003 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1004 args->print_dissections = print_dissections_collapsed;
1006 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY);
1007 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1008 args->print_dissections = print_dissections_as_displayed;
1010 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY);
1011 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1012 args->print_dissections = print_dissections_expanded;
1015 /* the details setting has priority over the radio buttons */
1016 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY);
1017 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1018 args->print_dissections = print_dissections_none;
1021 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY);
1022 args->print_hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1024 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY);
1025 args->print_formfeed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1028 window_destroy(GTK_WIDGET(parent_w));
1030 /* Now print/export the packets */
1032 status = cf_write_pdml_packets(&cfile, args);
1033 else if (export_as_psml)
1034 status = cf_write_psml_packets(&cfile, args);
1035 else if (export_as_csv)
1036 status = cf_write_csv_packets(&cfile, args);
1037 else if (export_as_carrays)
1038 status = cf_write_carrays_packets(&cfile, args);
1040 switch (args->format) {
1043 if (args->to_file) {
1044 args->stream = print_stream_text_new(TRUE, args->file);
1045 if (args->stream == NULL) {
1046 open_failure_alert_box(args->file, errno, TRUE);
1050 args->stream = print_stream_text_new(FALSE, args->cmd);
1051 if (args->stream == NULL) {
1052 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1053 "Couldn't run print command %s.", args->cmd);
1059 if (args->to_file) {
1060 args->stream = print_stream_ps_new(TRUE, args->file);
1061 if (args->stream == NULL) {
1062 open_failure_alert_box(args->file, errno, TRUE);
1066 args->stream = print_stream_ps_new(FALSE, args->cmd);
1067 if (args->stream == NULL) {
1068 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1069 "Couldn't run print command %s.", args->cmd);
1075 g_assert_not_reached();
1078 status = cf_print_packets(&cfile, args);
1085 case CF_PRINT_OPEN_ERROR:
1087 open_failure_alert_box(args->file, errno, TRUE);
1089 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't run print command %s.",
1093 case CF_PRINT_WRITE_ERROR:
1095 write_failure_alert_box(args->file, errno);
1097 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1098 "Error writing to print command: %s", strerror(errno));
1104 print_mswin(args->file);
1106 /* trash temp file */
1107 eth_remove(args->file);
1109 /* restore old settings */
1110 args->to_file = FALSE;
1111 args->file = tmp_oldfile;
1117 print_destroy_cb(GtkWidget *win, gpointer user_data)
1121 /* Is there a file selection dialog associated with this
1122 Print File dialog? */
1123 fs = g_object_get_data(G_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
1126 /* Yes. Destroy it. */
1130 /* Note that we no longer have a "Print" dialog box. */
1131 *((gpointer *) user_data) = NULL;