2 * Dialog boxes for printing and exporting to text files
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 #include <epan/prefs.h>
37 #include "alert_box.h"
38 #include "simple_dialog.h"
41 #include "dlg_utils.h"
43 #include <epan/epan_dissect.h>
44 #include <epan/filesystem.h>
47 #include "print_mswin.h"
49 #include "compat_macros.h"
50 #include "range_utils.h"
53 /* dialog output action */
55 output_action_print, /* print text to printer */
56 output_action_export_text, /* export to plain text */
57 output_action_export_ps, /* export to postscript */
58 output_action_export_psml, /* export to packet summary markup language */
59 output_action_export_pdml /* export to packet data markup language */
63 /* On Win32, a GUI application apparently can't use "popen()" (it
64 "returns an invalid file handle, if used in a Windows program,
65 that will cause the program to hang indefinitely"), so we can't
66 use a pipe to a print command to print to a printer.
68 Eventually, we should try to use the native Win32 printing API
69 for this (and also use various UNIX printing APIs, when present?).
73 open_print_dialog(char *title, output_action_e action, print_args_t *args);
74 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
75 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
76 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
77 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
81 #define PRINT_ARGS_KEY "printer_args"
83 #define PRINT_PS_RB_KEY "printer_ps_radio_button"
84 #define PRINT_PDML_RB_KEY "printer_pdml_radio_button"
85 #define PRINT_PSML_RB_KEY "printer_psml_radio_button"
86 #define PRINT_DEST_CB_KEY "printer_destination_check_button"
88 #define PRINT_SUMMARY_CB_KEY "printer_summary_check_button"
89 #define PRINT_DETAILS_CB_KEY "printer_details_check_button"
90 #define PRINT_COLLAPSE_ALL_RB_KEY "printer_collapse_all_radio_button"
91 #define PRINT_AS_DISPLAYED_RB_KEY "printer_as_displayed_radio_button"
92 #define PRINT_EXPAND_ALL_RB_KEY "printer_expand_all_radio_button"
93 #define PRINT_HEX_CB_KEY "printer_hex_check_button"
94 #define PRINT_FORMFEED_CB_KEY "printer_formfeed_check_button"
96 #define PRINT_BT_KEY "printer_button"
98 #define PRINT_TE_PTR_KEY "printer_file_te_ptr"
102 * Keep a static pointer to the current "Print" window, if any, so that if
103 * somebody tries to do "File:Print" while there's already a "Print" window
104 * up, we just pop up the existing one, rather than creating a new one.
106 static GtkWidget *print_win = NULL;
108 static print_args_t print_args;
110 static gboolean print_prefs_init = FALSE;
114 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
116 print_args_t *args = &print_args;
118 if (print_win != NULL) {
119 /* There's already a "Print" dialog box; reactivate it. */
120 reactivate_window(print_win);
124 /* get settings from preferences (and other initial values) only once */
125 if(print_prefs_init == FALSE) {
126 print_prefs_init = TRUE;
127 args->format = prefs.pr_format;
128 args->to_file = prefs.pr_dest;
129 args->file = g_strdup(prefs.pr_file);
130 args->cmd = g_strdup(prefs.pr_cmd);
131 args->print_summary = TRUE;
132 args->print_dissections = print_dissections_as_displayed;
133 args->print_hex = FALSE;
134 args->print_formfeed = FALSE;
136 /* init the printing range */
137 packet_range_init(&args->range);
140 print_win = open_print_dialog("Ethereal: Print", output_action_print, args);
141 SIGNAL_CONNECT(print_win, "destroy", print_destroy_cb, &print_win);
146 * Keep a static pointer to the current "Export text" window, if any, so that if
147 * somebody tries to do "File:Export to text" while there's already a "Export text" window
148 * up, we just pop up the existing one, rather than creating a new one.
150 static GtkWidget *export_text_win = NULL;
152 static print_args_t export_text_args;
154 static gboolean export_text_prefs_init = FALSE;
158 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
160 print_args_t *args = &export_text_args;
162 if (export_text_win != NULL) {
163 /* There's already a "Export text" dialog box; reactivate it. */
164 reactivate_window(export_text_win);
168 /* get settings from preferences (and other initial values) only once */
169 if(export_text_prefs_init == FALSE) {
170 export_text_prefs_init = TRUE;
171 args->format = PR_FMT_TEXT;
172 args->to_file = TRUE;
173 args->file = g_strdup("");
174 args->cmd = g_strdup("");
175 args->print_summary = TRUE;
176 args->print_dissections = print_dissections_as_displayed;
177 args->print_hex = FALSE;
178 args->print_formfeed = FALSE;
180 /* init the printing range */
181 packet_range_init(&args->range);
184 export_text_win = open_print_dialog("Ethereal: Export as \"Plain Text\" File", output_action_export_text, args);
185 SIGNAL_CONNECT(export_text_win, "destroy", print_destroy_cb, &export_text_win);
190 * Keep a static pointer to the current "Export ps" window, if any, so that if
191 * somebody tries to do "File:Export to ps" while there's already a "Export ps" window
192 * up, we just pop up the existing one, rather than creating a new one.
194 static GtkWidget *export_ps_win = NULL;
196 static print_args_t export_ps_args;
198 static gboolean export_ps_prefs_init = FALSE;
202 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
204 print_args_t *args = &export_ps_args;
206 if (export_ps_win != NULL) {
207 /* There's already a "Export ps" dialog box; reactivate it. */
208 reactivate_window(export_ps_win);
212 /* get settings from preferences (and other initial values) only once */
213 if(export_ps_prefs_init == FALSE) {
214 export_ps_prefs_init = TRUE;
215 args->format = PR_FMT_PS;
216 args->to_file = TRUE;
217 args->file = g_strdup("");
218 args->cmd = g_strdup("");
219 args->print_summary = TRUE;
220 args->print_dissections = print_dissections_as_displayed;
221 args->print_hex = FALSE;
222 args->print_formfeed = FALSE;
224 /* init the printing range */
225 packet_range_init(&args->range);
228 export_ps_win = open_print_dialog("Ethereal: Export as \"PostScript\" file", output_action_export_ps, args);
229 SIGNAL_CONNECT(export_ps_win, "destroy", print_destroy_cb, &export_ps_win);
234 * Keep a static pointer to the current "Export psml" window, if any, so that if
235 * somebody tries to do "File:Export to psml" while there's already a "Export psml" window
236 * up, we just pop up the existing one, rather than creating a new one.
238 static GtkWidget *export_psml_win = NULL;
240 static print_args_t export_psml_args;
242 static gboolean export_psml_prefs_init = FALSE;
246 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
248 print_args_t *args = &export_psml_args;
250 if (export_psml_win != NULL) {
251 /* There's already a "Export psml" dialog box; reactivate it. */
252 reactivate_window(export_psml_win);
256 /* get settings from preferences (and other initial values) only once */
257 if(export_psml_prefs_init == FALSE) {
258 export_psml_prefs_init = TRUE;
259 args->format = PR_FMT_TEXT; /* XXX */
260 args->to_file = TRUE;
261 args->file = g_strdup("");
262 args->cmd = g_strdup("");
263 args->print_summary = TRUE;
264 args->print_dissections = print_dissections_as_displayed;
265 args->print_hex = FALSE;
266 args->print_formfeed = FALSE;
268 /* init the printing range */
269 packet_range_init(&args->range);
272 export_psml_win = open_print_dialog("Ethereal: Export as \"PSML\" file", output_action_export_psml, args);
273 SIGNAL_CONNECT(export_psml_win, "destroy", print_destroy_cb, &export_psml_win);
278 * Keep a static pointer to the current "Export pdml" window, if any, so that if
279 * somebody tries to do "File:Export to pdml" while there's already a "Export pdml" window
280 * up, we just pop up the existing one, rather than creating a new one.
282 static GtkWidget *export_pdml_win = NULL;
284 static print_args_t export_pdml_args;
286 static gboolean export_pdml_prefs_init = FALSE;
290 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
292 print_args_t *args = &export_pdml_args;
294 if (export_pdml_win != NULL) {
295 /* There's already a "Export pdml" dialog box; reactivate it. */
296 reactivate_window(export_pdml_win);
300 /* get settings from preferences (and other initial values) only once */
301 if(export_pdml_prefs_init == FALSE) {
302 export_pdml_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;
312 /* init the printing range */
313 packet_range_init(&args->range);
316 export_pdml_win = open_print_dialog("Ethereal: Export as \"PDML\" file", output_action_export_pdml, args);
317 SIGNAL_CONNECT(export_pdml_win, "destroy", print_destroy_cb, &export_pdml_win);
322 print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
324 file_selection_browse(file_bt, file_te, "Ethereal: Print to File",
325 FILE_SELECTION_WRITE_BROWSE);
330 /* Open the print dialog */
332 open_print_dialog(char *title, output_action_e action, print_args_t *args)
334 #if GTK_MAJOR_VERSION < 2
335 GtkAccelGroup *accel_group;
341 GtkWidget *printer_fr, *printer_vb, *export_format_lb;
342 GtkWidget *text_rb, *ps_rb, *pdml_rb, *psml_rb;
343 GtkWidget *printer_tb, *dest_cb;
345 GtkWidget *cmd_lb, *cmd_te;
347 GtkWidget *file_bt, *file_te;
349 GtkWidget *range_fr, *range_tb;
351 GtkWidget *packet_hb;
353 GtkWidget *format_fr, *format_vb;
354 GtkWidget *summary_cb;
356 GtkWidget *details_cb;
357 GtkWidget *details_hb, *details_vb;
358 GtkWidget *collapse_all_rb, *as_displayed_rb, *expand_all_rb;
360 GtkWidget *sep, *formfeed_cb;
362 GtkWidget *bbox, *ok_bt, *cancel_bt;
364 GtkTooltips *tooltips;
368 main_win = dlg_window_new(title);
370 /* Enable tooltips */
371 tooltips = gtk_tooltips_new();
373 #if GTK_MAJOR_VERSION < 2
374 /* Accelerator group for the accelerators (or, as they're called in
375 Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
376 Ctrl+<key> is an accelerator). */
377 accel_group = gtk_accel_group_new();
378 gtk_window_add_accel_group(GTK_WINDOW(main_win), accel_group);
381 /* Vertical enclosing container for each row of widgets */
382 main_vb = gtk_vbox_new(FALSE, 5);
383 gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
384 gtk_container_add(GTK_CONTAINER(main_win), main_vb);
385 gtk_widget_show(main_vb);
387 /*****************************************************/
389 /*** printer frame ***/
390 printer_fr = gtk_frame_new(action == output_action_print ? "Printer" : "Export to file:");
391 gtk_box_pack_start(GTK_BOX(main_vb), printer_fr, FALSE, FALSE, 0);
392 gtk_widget_show(printer_fr);
393 printer_vb = gtk_vbox_new(FALSE, 5);
394 gtk_container_border_width(GTK_CONTAINER(printer_vb), 5);
395 gtk_container_add(GTK_CONTAINER(printer_fr), printer_vb);
396 gtk_widget_show(printer_vb);
398 /* "Plain text" / "Postscript" / "PDML", ... radio buttons */
399 text_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "Plain _text", accel_group);
400 if (args->format == PR_FMT_TEXT)
401 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(text_rb), TRUE);
402 gtk_tooltips_set_tip (tooltips, text_rb, "Print output in ascii \"plain text\" format. If you're unsure, use this format.", NULL);
403 gtk_box_pack_start(GTK_BOX(printer_vb), text_rb, FALSE, FALSE, 0);
404 if(action == output_action_print)
405 gtk_widget_show(text_rb);
407 ps_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "_PostScript", accel_group);
408 if (args->format == PR_FMT_PS)
409 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ps_rb), TRUE);
410 gtk_tooltips_set_tip (tooltips, ps_rb, "Print output in \"postscript\" format, for postscript capable printers or print servers.", NULL);
411 gtk_box_pack_start(GTK_BOX(printer_vb), ps_rb, FALSE, FALSE, 0);
412 if(action == output_action_print)
413 gtk_widget_show(ps_rb);
415 pdml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PDM_L (XML: Packet Details Markup Language)", accel_group);
416 if (action == output_action_export_pdml)
417 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(pdml_rb), TRUE);
418 gtk_tooltips_set_tip (tooltips, pdml_rb,
419 "Print output in \"PDML\" (Packet Details Markup Language), "
420 "an XML based packet data interchange format. "
421 "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.", NULL);
422 gtk_box_pack_start(GTK_BOX(printer_vb), pdml_rb, FALSE, FALSE, 0);
423 /* gtk_widget_show(pdml_rb); */
425 psml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PSML (XML: Packet Summary Markup Language)", accel_group);
426 if (action == output_action_export_psml)
427 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(psml_rb), TRUE);
428 gtk_tooltips_set_tip (tooltips, psml_rb,
429 "Print output in \"PSML\" (Packet Summary Markup Language), "
430 "an XML based packet summary interchange format. "
431 "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.", NULL);
432 gtk_box_pack_start(GTK_BOX(printer_vb), psml_rb, FALSE, FALSE, 0);
433 /* gtk_widget_show(psml_rb); */
437 printer_tb = gtk_table_new(2, 3, FALSE);
439 printer_tb = gtk_table_new(2, 2, FALSE);
441 gtk_box_pack_start(GTK_BOX(printer_vb), printer_tb, FALSE, FALSE, 0);
442 gtk_table_set_row_spacings(GTK_TABLE(printer_tb), 5);
443 gtk_table_set_col_spacings(GTK_TABLE(printer_tb), 5);
444 gtk_widget_show(printer_tb);
447 /* Output to file button */
448 dest_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Output to _file:", accel_group);
450 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
451 gtk_tooltips_set_tip (tooltips, dest_cb, "Output to file instead of printer", NULL);
452 gtk_table_attach_defaults(GTK_TABLE(printer_tb), dest_cb, 0, 1, 0, 1);
453 if(action == output_action_print)
454 gtk_widget_show(dest_cb);
456 /* File text entry */
457 file_te = gtk_entry_new();
458 OBJECT_SET_DATA(dest_cb, PRINT_FILE_TE_KEY, file_te);
459 gtk_tooltips_set_tip (tooltips, file_te, "Enter Output filename", NULL);
460 gtk_entry_set_text(GTK_ENTRY(file_te), args->file);
461 gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_te, 1, 2, 0, 1);
462 gtk_widget_set_sensitive(file_te, args->to_file);
463 gtk_widget_show(file_te);
465 gtk_widget_grab_focus(file_te);
467 /* "Browse" button */
468 file_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_BROWSE);
469 OBJECT_SET_DATA(dest_cb, PRINT_FILE_BT_KEY, file_bt);
470 OBJECT_SET_DATA(file_bt, PRINT_TE_PTR_KEY, file_te);
471 gtk_tooltips_set_tip (tooltips, file_bt, "Browse output filename in filesystem", NULL);
472 gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_bt, 2, 3, 0, 1);
473 gtk_widget_set_sensitive(file_bt, args->to_file);
474 gtk_widget_show(file_bt);
476 /* Command label and text entry */
478 cmd_lb = gtk_label_new("Print command:");
479 OBJECT_SET_DATA(dest_cb, PRINT_CMD_LB_KEY, cmd_lb);
480 gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
481 gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_lb, 0, 1, 1, 2);
482 gtk_widget_set_sensitive(cmd_lb, !args->to_file);
483 if(action == output_action_print)
484 gtk_widget_show(cmd_lb);
486 cmd_te = gtk_entry_new();
487 OBJECT_SET_DATA(dest_cb, PRINT_CMD_TE_KEY, cmd_te);
488 gtk_tooltips_set_tip (tooltips, cmd_te, "Enter print command", NULL);
489 gtk_entry_set_text(GTK_ENTRY(cmd_te), args->cmd);
490 gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_te, 1, 2, 1, 2);
491 gtk_widget_set_sensitive(cmd_te, !args->to_file);
492 if(action == output_action_print)
493 gtk_widget_show(cmd_te);
496 SIGNAL_CONNECT(dest_cb, "toggled", print_cmd_toggle_dest, NULL);
497 SIGNAL_CONNECT(file_bt, "clicked", print_browse_file_cb, file_te);
499 if(action == output_action_export_ps) {
500 export_format_lb = gtk_label_new("(PostScript files can be easily converted to PDF files using ghostscript's ps2pdf)");
501 gtk_box_pack_start(GTK_BOX(printer_vb), export_format_lb, FALSE, FALSE, 0);
502 gtk_widget_show(export_format_lb);
505 /*****************************************************/
507 /*** hor box for range and format frames ***/
508 packet_hb = gtk_hbox_new(FALSE, 5);
509 gtk_container_add(GTK_CONTAINER(main_vb), packet_hb);
510 gtk_widget_show(packet_hb);
512 /*** packet range frame ***/
513 range_fr = gtk_frame_new("Packet Range");
514 gtk_box_pack_start(GTK_BOX(packet_hb), range_fr, FALSE, FALSE, 0);
515 gtk_widget_show(range_fr);
517 range_tb = range_new(&args->range
518 #if GTK_MAJOR_VERSION < 2
522 gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
523 gtk_widget_show(range_tb);
525 /*****************************************************/
527 /*** packet format frame ***/
528 format_fr = gtk_frame_new("Packet Format");
529 gtk_box_pack_start(GTK_BOX(packet_hb), format_fr, TRUE, TRUE, 0);
530 if( action == output_action_print ||
531 action == output_action_export_text ||
532 action == output_action_export_ps)
533 gtk_widget_show(format_fr);
534 format_vb = gtk_vbox_new(FALSE, 5);
535 gtk_container_border_width(GTK_CONTAINER(format_vb), 5);
536 gtk_container_add(GTK_CONTAINER(format_fr), format_vb);
537 gtk_widget_show(format_vb);
539 /* "Print summary line" check button */
540 summary_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Packet summary line", accel_group);
541 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(summary_cb), args->print_summary);
542 SIGNAL_CONNECT(summary_cb, "clicked", print_cmd_toggle_detail, main_win);
543 gtk_tooltips_set_tip (tooltips, summary_cb, "Output of a packet summary line, like in the packet list", NULL);
544 gtk_container_add(GTK_CONTAINER(format_vb), summary_cb);
545 gtk_widget_show(summary_cb);
548 /* "Details" check button */
549 details_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Packet details:", accel_group);
550 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(details_cb), args->print_dissections != print_dissections_none);
551 SIGNAL_CONNECT(details_cb, "clicked", print_cmd_toggle_detail, main_win);
552 gtk_tooltips_set_tip (tooltips, details_cb, "Output format of the selected packet details (protocol tree).", NULL);
553 gtk_container_add(GTK_CONTAINER(format_vb), details_cb);
554 gtk_widget_show(details_cb);
556 /*** packet details ***/
557 details_hb = gtk_hbox_new(FALSE, 6);
558 gtk_container_border_width(GTK_CONTAINER(details_hb), 0);
559 gtk_container_add(GTK_CONTAINER(format_vb), details_hb);
560 gtk_widget_show(details_hb);
562 details_vb = gtk_vbox_new(FALSE, 6);
563 gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
564 gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
565 gtk_widget_show(details_vb);
567 details_vb = gtk_vbox_new(FALSE, 6);
568 gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
569 gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
570 gtk_widget_show(details_vb);
572 /* "All collapsed"/"As displayed"/"All Expanded" radio buttons */
573 collapse_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "All co_llapsed", accel_group);
574 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(collapse_all_rb), args->print_dissections == print_dissections_collapsed);
575 gtk_tooltips_set_tip (tooltips, collapse_all_rb, "Output of the packet details tree \"collapsed\"", NULL);
576 gtk_container_add(GTK_CONTAINER(details_vb), collapse_all_rb);
577 gtk_widget_show(collapse_all_rb);
579 as_displayed_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "As displa_yed", accel_group);
580 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(as_displayed_rb), args->print_dissections == print_dissections_as_displayed);
581 gtk_tooltips_set_tip (tooltips, as_displayed_rb, "Output of the packet details tree \"as displayed\"", NULL);
582 gtk_container_add(GTK_CONTAINER(details_vb), as_displayed_rb);
583 gtk_widget_show(as_displayed_rb);
585 expand_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "All e_xpanded", accel_group);
586 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(expand_all_rb), args->print_dissections == print_dissections_expanded);
587 gtk_tooltips_set_tip (tooltips, expand_all_rb, "Output of the packet details tree \"expanded\"", NULL);
588 gtk_container_add(GTK_CONTAINER(details_vb), expand_all_rb);
589 gtk_widget_show(expand_all_rb);
591 /* "Print hex" check button. */
592 hex_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Packet bytes", accel_group);
593 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_cb), args->print_hex);
594 SIGNAL_CONNECT(hex_cb, "clicked", print_cmd_toggle_detail, main_win);
595 gtk_tooltips_set_tip (tooltips, hex_cb, "Add a hexdump of the packet data", NULL);
596 gtk_container_add(GTK_CONTAINER(format_vb), hex_cb);
597 gtk_widget_show(hex_cb);
600 sep = gtk_hseparator_new();
601 gtk_container_add(GTK_CONTAINER(format_vb), sep);
602 gtk_widget_show(sep);
604 /* "Each packet on a new page" check button. */
605 formfeed_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Each packet on a new page", accel_group);
606 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(formfeed_cb), args->print_formfeed);
607 gtk_tooltips_set_tip (tooltips, formfeed_cb, "When checked, a new page will be used for each packet. "
608 "This is done by adding a formfeed (or similar) between the packet outputs.", NULL);
609 gtk_container_add(GTK_CONTAINER(format_vb), formfeed_cb);
610 gtk_widget_show(formfeed_cb);
613 OBJECT_SET_DATA(main_win, PRINT_ARGS_KEY, args);
614 OBJECT_SET_DATA(main_win, PRINT_SUMMARY_CB_KEY, summary_cb);
615 OBJECT_SET_DATA(main_win, PRINT_DETAILS_CB_KEY, details_cb);
616 OBJECT_SET_DATA(main_win, PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
617 OBJECT_SET_DATA(main_win, PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
618 OBJECT_SET_DATA(main_win, PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
619 OBJECT_SET_DATA(main_win, PRINT_HEX_CB_KEY, hex_cb);
621 /*****************************************************/
625 bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL);
626 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
627 gtk_widget_show(bbox);
629 ok_bt = OBJECT_GET_DATA(bbox, action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK);
631 OBJECT_SET_DATA(main_win, PRINT_BT_KEY, ok_bt);
633 OBJECT_SET_DATA(ok_bt, PRINT_PS_RB_KEY, ps_rb);
634 OBJECT_SET_DATA(ok_bt, PRINT_PDML_RB_KEY, pdml_rb);
635 OBJECT_SET_DATA(ok_bt, PRINT_PSML_RB_KEY, psml_rb);
636 OBJECT_SET_DATA(ok_bt, PRINT_DEST_CB_KEY, dest_cb);
638 OBJECT_SET_DATA(ok_bt, PRINT_CMD_TE_KEY, cmd_te);
641 OBJECT_SET_DATA(ok_bt, PRINT_ARGS_KEY, args);
642 OBJECT_SET_DATA(ok_bt, PRINT_FILE_TE_KEY, file_te);
643 OBJECT_SET_DATA(ok_bt, PRINT_SUMMARY_CB_KEY, summary_cb);
644 OBJECT_SET_DATA(ok_bt, PRINT_DETAILS_CB_KEY, details_cb);
645 OBJECT_SET_DATA(ok_bt, PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
646 OBJECT_SET_DATA(ok_bt, PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
647 OBJECT_SET_DATA(ok_bt, PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
648 OBJECT_SET_DATA(ok_bt, PRINT_HEX_CB_KEY, hex_cb);
649 OBJECT_SET_DATA(ok_bt, PRINT_FORMFEED_CB_KEY, formfeed_cb);
650 SIGNAL_CONNECT(ok_bt, "clicked", print_ok_cb, main_win);
651 gtk_tooltips_set_tip (tooltips, ok_bt, "Start output", NULL);
653 cancel_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
654 window_set_cancel_button(main_win, cancel_bt, window_cancel_button_cb);
655 gtk_tooltips_set_tip (tooltips, cancel_bt, "Cancel and exit dialog", NULL);
657 gtk_widget_grab_default(ok_bt);
659 /* Catch the "activate" signal on the "Command" and "File" text entries,
660 so that if the user types Return there, we act as if the "OK" button
661 had been selected, as happens if Return is typed if some widget
662 that *doesn't* handle the Return key has the input focus. */
664 dlg_set_activate(cmd_te, ok_bt);
666 if(action != output_action_print)
667 dlg_set_activate(file_te, ok_bt);
669 SIGNAL_CONNECT(main_win, "delete_event", window_delete_event_cb, NULL);
671 gtk_widget_show(main_win);
672 window_present(main_win);
678 /* user changed "print to" destination */
680 print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
683 GtkWidget *cmd_lb, *cmd_te;
685 GtkWidget *file_bt, *file_te;
689 cmd_lb = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_CMD_LB_KEY));
690 cmd_te = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_CMD_TE_KEY));
692 file_bt = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_FILE_BT_KEY));
693 file_te = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_FILE_TE_KEY));
695 to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
697 gtk_widget_set_sensitive(cmd_lb, !to_file);
698 gtk_widget_set_sensitive(cmd_te, !to_file);
700 gtk_widget_set_sensitive(file_bt, to_file);
701 gtk_widget_set_sensitive(file_te, to_file);
705 /* user changed "packet details" */
707 print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
709 GtkWidget *print_bt, *summary_cb, *details_cb, *collapse_all_rb, *expand_all_rb, *as_displayed_rb, *hex_cb;
710 gboolean print_detail;
713 print_bt = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_BT_KEY));
714 summary_cb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_SUMMARY_CB_KEY));
715 details_cb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_DETAILS_CB_KEY));
716 collapse_all_rb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_COLLAPSE_ALL_RB_KEY));
717 as_displayed_rb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_AS_DISPLAYED_RB_KEY));
718 expand_all_rb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_EXPAND_ALL_RB_KEY));
719 hex_cb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_HEX_CB_KEY));
721 /* is user disabled details, disable the corresponding buttons */
722 print_detail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb));
723 gtk_widget_set_sensitive(collapse_all_rb, print_detail);
724 gtk_widget_set_sensitive(as_displayed_rb, print_detail);
725 gtk_widget_set_sensitive(expand_all_rb, print_detail);
727 /* if user selected nothing to print at all, disable the "ok" button */
728 gtk_widget_set_sensitive(print_bt,
729 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (summary_cb)) ||
730 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb)) ||
731 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_cb)));
736 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
743 gboolean export_as_pdml = FALSE, export_as_psml = FALSE;
745 gboolean win_printer = FALSE;
749 args = (print_args_t *)OBJECT_GET_DATA(ok_bt, PRINT_ARGS_KEY);
751 /* Check whether the range is valid. */
752 if (!range_check_validity(&args->range)) {
753 /* The range isn't valid; don't dismiss the print/export dialog box,
754 just leave it around so that the user can, after they
755 dismiss the alert box popped up for the error, try again. */
759 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DEST_CB_KEY);
760 args->to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
763 g_dest = gtk_entry_get_text(GTK_ENTRY(OBJECT_GET_DATA(ok_bt,
764 PRINT_FILE_TE_KEY)));
766 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
767 "Output to file, but no file specified.");
771 args->file = g_strdup(g_dest);
772 /* Save the directory name for future file dialogs. */
773 f_name = g_strdup(g_dest);
774 dirname = get_dirname(f_name); /* Overwrites f_name */
775 set_last_open_dir(dirname);
780 /*XXX should use temp file stuff in util routines */
782 args->file = g_strdup(tmpnam(NULL));
783 args->to_file = TRUE;
786 args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(OBJECT_GET_DATA(ok_bt,
787 PRINT_CMD_TE_KEY))));
791 args->format = PR_FMT_TEXT;
792 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_PS_RB_KEY);
793 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
794 args->format = PR_FMT_PS;
795 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_PDML_RB_KEY);
796 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
797 export_as_pdml = TRUE;
798 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_PSML_RB_KEY);
799 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
800 export_as_psml = TRUE;
802 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_SUMMARY_CB_KEY);
803 args->print_summary = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
805 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_COLLAPSE_ALL_RB_KEY);
806 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
807 args->print_dissections = print_dissections_collapsed;
809 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_AS_DISPLAYED_RB_KEY);
810 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
811 args->print_dissections = print_dissections_as_displayed;
813 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_EXPAND_ALL_RB_KEY);
814 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
815 args->print_dissections = print_dissections_expanded;
818 /* the details setting has priority over the radio buttons */
819 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DETAILS_CB_KEY);
820 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
821 args->print_dissections = print_dissections_none;
824 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_HEX_CB_KEY);
825 args->print_hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
827 button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_FORMFEED_CB_KEY);
828 args->print_formfeed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
831 window_destroy(GTK_WIDGET(parent_w));
833 /* Now print/export the packets */
835 status = write_pdml_packets(&cfile, args);
836 else if (export_as_psml)
837 status = write_psml_packets(&cfile, args);
839 switch (args->format) {
843 args->stream = print_stream_text_new(TRUE, args->file);
844 if (args->stream == NULL) {
845 open_failure_alert_box(args->file, errno, TRUE);
849 args->stream = print_stream_text_new(FALSE, args->cmd);
850 if (args->stream == NULL) {
851 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
852 "Couldn't run print command %s.", args->cmd);
859 args->stream = print_stream_ps_new(TRUE, args->file);
860 if (args->stream == NULL) {
861 open_failure_alert_box(args->file, errno, TRUE);
865 args->stream = print_stream_ps_new(FALSE, args->cmd);
866 if (args->stream == NULL) {
867 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
868 "Couldn't run print command %s.", args->cmd);
874 g_assert_not_reached();
877 status = print_packets(&cfile, args);
886 open_failure_alert_box(args->file, errno, TRUE);
888 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't run print command %s.",
894 write_failure_alert_box(args->file, errno);
896 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
897 "Error writing to print command: %s", strerror(errno));
903 print_mswin(args->file);
905 /* trash temp file */
912 print_destroy_cb(GtkWidget *win, gpointer user_data)
916 /* Is there a file selection dialog associated with this
917 Print File dialog? */
918 fs = OBJECT_GET_DATA(win, E_FILE_SEL_DIALOG_PTR_KEY);
921 /* Yes. Destroy it. */
925 /* Note that we no longer have a "Print" dialog box. */
926 *((gpointer *) user_data) = NULL;