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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/prefs.h>
32 #include <epan/epan_dissect.h>
33 #include <epan/filesystem.h>
36 #include "ui/alert_box.h"
37 #include "ui/simple_dialog.h"
39 #include <wsutil/file_util.h>
41 #include "ui/gtk/gtkglobals.h"
42 #include "ui/gtk/keys.h"
43 #include "ui/gtk/gui_utils.h"
44 #include "ui/gtk/dlg_utils.h"
45 #include "ui/gtk/file_dlg.h"
46 #include "ui/gtk/main.h"
47 #include "ui/gtk/stock_icons.h"
48 #include "ui/gtk/range_utils.h"
49 #include "ui/gtk/help_dlg.h"
52 #include <gdk/gdkwin32.h>
54 #include "ui/win32/file_dlg_win32.h"
55 #include "ui/win32/print_win32.h"
59 /* dialog output action */
61 output_action_print, /* print text to printer */
62 output_action_export_text, /* export to plain text */
63 output_action_export_ps, /* export to postscript */
64 output_action_export_psml, /* export to packet summary markup language */
65 output_action_export_pdml, /* export to packet data markup language */
66 output_action_export_csv, /* export to csv file */
67 output_action_export_carrays /* export to C array file */
71 /* On Win32, a GUI application apparently can't use "popen()" (it
72 "returns an invalid file handle, if used in a Windows program,
73 that will cause the program to hang indefinitely"), so we can't
74 use a pipe to a print command to print to a printer.
76 Eventually, we should try to use the native Win32 printing API
77 for this (and also use various UNIX printing APIs, when present?).
81 open_print_dialog(const char *title, output_action_e action, print_args_t *args);
82 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
83 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
84 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
85 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
89 #define PRINT_ARGS_KEY "printer_args"
91 #define PRINT_PS_RB_KEY "printer_ps_radio_button"
92 #define PRINT_PDML_RB_KEY "printer_pdml_radio_button"
93 #define PRINT_PSML_RB_KEY "printer_psml_radio_button"
94 #define PRINT_CSV_RB_KEY "printer_csv_radio_button"
95 #define PRINT_CARRAYS_RB_KEY "printer_carrays_radio_button"
96 #define PRINT_DEST_CB_KEY "printer_destination_check_button"
98 #define PRINT_SUMMARY_CB_KEY "printer_summary_check_button"
99 #define PRINT_DETAILS_CB_KEY "printer_details_check_button"
100 #define PRINT_COLLAPSE_ALL_RB_KEY "printer_collapse_all_radio_button"
101 #define PRINT_AS_DISPLAYED_RB_KEY "printer_as_displayed_radio_button"
102 #define PRINT_EXPAND_ALL_RB_KEY "printer_expand_all_radio_button"
103 #define PRINT_HEX_CB_KEY "printer_hex_check_button"
104 #define PRINT_FORMFEED_CB_KEY "printer_formfeed_check_button"
106 #define PRINT_BT_KEY "printer_button"
108 #define PRINT_TE_PTR_KEY "printer_file_te_ptr"
112 * Keep a static pointer to the current "Print" window, if any, so that if
113 * somebody tries to do "File:Print" while there's already a "Print" window
114 * up, we just pop up the existing one, rather than creating a new one.
116 static GtkWidget *print_win = NULL;
118 static print_args_t print_args;
120 static gboolean print_prefs_init = FALSE;
124 file_print_cmd(gboolean print_selected)
126 print_args_t *args = &print_args;
128 if (print_win != NULL) {
129 /* There's already a "Print" dialog box; reactivate it. */
130 reactivate_window(print_win);
134 /* get settings from preferences (and other initial values) only once */
135 if(print_prefs_init == FALSE) {
136 print_prefs_init = TRUE;
137 args->format = (print_format_e)prefs.pr_format;
138 args->to_file = prefs.pr_dest;
139 args->file = g_strdup(prefs.pr_file);
140 args->cmd = g_strdup(prefs.pr_cmd);
141 args->print_summary = TRUE;
142 args->print_dissections = print_dissections_as_displayed;
143 args->print_hex = FALSE;
144 args->print_formfeed = FALSE;
147 /* init the printing range */
148 packet_range_init(&args->range, &cfile);
149 args->range.process_filtered = TRUE;
152 args->range.process = range_process_selected;
155 print_win = open_print_dialog("Wireshark: Print", output_action_print, args);
156 g_signal_connect(print_win, "destroy", G_CALLBACK(print_destroy_cb), &print_win);
160 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
162 file_print_cmd(FALSE);
166 file_print_selected_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
168 file_print_cmd(TRUE);
172 * Keep a static pointer to the current "Export text" window, if any, so that if
173 * somebody tries to do "File:Export to text" while there's already a "Export text" window
174 * up, we just pop up the existing one, rather than creating a new one.
176 static GtkWidget *export_text_win = NULL;
178 static print_args_t export_text_args;
180 static gboolean export_text_prefs_init = FALSE;
185 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
187 win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_text);
192 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
194 print_args_t *args = &export_text_args;
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, &cfile);
217 args->range.process_filtered = TRUE;
219 export_text_win = open_print_dialog("Wireshark: Export as \"Plain Text\" File", output_action_export_text, args);
220 g_signal_connect(export_text_win, "destroy", G_CALLBACK(print_destroy_cb), &export_text_win);
226 * Keep a static pointer to the current "Export ps" window, if any, so that if
227 * somebody tries to do "File:Export to ps" while there's already a "Export ps" window
228 * up, we just pop up the existing one, rather than creating a new one.
230 static GtkWidget *export_ps_win = NULL;
232 static print_args_t export_ps_args;
234 static gboolean export_ps_prefs_init = FALSE;
239 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
241 win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_ps);
246 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
248 print_args_t *args = &export_ps_args;
250 if (export_ps_win != NULL) {
251 /* There's already a "Export ps" dialog box; reactivate it. */
252 reactivate_window(export_ps_win);
256 /* get settings from preferences (and other initial values) only once */
257 if(export_ps_prefs_init == FALSE) {
258 export_ps_prefs_init = TRUE;
259 args->format = PR_FMT_PS;
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;
269 /* init the printing range */
270 packet_range_init(&args->range, &cfile);
271 args->range.process_filtered = TRUE;
273 export_ps_win = open_print_dialog("Wireshark: Export as \"PostScript\" file", output_action_export_ps, args);
274 g_signal_connect(export_ps_win, "destroy", G_CALLBACK(print_destroy_cb), &export_ps_win);
280 * Keep a static pointer to the current "Export psml" window, if any, so that if
281 * somebody tries to do "File:Export to psml" while there's already a "Export psml" window
282 * up, we just pop up the existing one, rather than creating a new one.
284 static GtkWidget *export_psml_win = NULL;
286 static print_args_t export_psml_args;
288 static gboolean export_psml_prefs_init = FALSE;
293 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
295 win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_psml);
300 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
302 print_args_t *args = &export_psml_args;
304 if (export_psml_win != NULL) {
305 /* There's already a "Export psml" dialog box; reactivate it. */
306 reactivate_window(export_psml_win);
310 /* get settings from preferences (and other initial values) only once */
311 if(export_psml_prefs_init == FALSE) {
312 export_psml_prefs_init = TRUE;
313 args->format = PR_FMT_TEXT; /* XXX */
314 args->to_file = TRUE;
315 args->file = g_strdup("");
316 args->cmd = g_strdup("");
317 args->print_summary = TRUE;
318 args->print_dissections = print_dissections_as_displayed;
319 args->print_hex = FALSE;
320 args->print_formfeed = FALSE;
323 /* init the printing range */
324 packet_range_init(&args->range, &cfile);
325 args->range.process_filtered = TRUE;
327 export_psml_win = open_print_dialog("Wireshark: Export as \"PSML\" file", output_action_export_psml, args);
328 g_signal_connect(export_psml_win, "destroy", G_CALLBACK(print_destroy_cb), &export_psml_win);
333 * Keep a static pointer to the current "Export pdml" window, if any, so that if
334 * somebody tries to do "File:Export to pdml" while there's already a "Export pdml" window
335 * up, we just pop up the existing one, rather than creating a new one.
337 static GtkWidget *export_pdml_win = NULL;
339 static print_args_t export_pdml_args;
341 static gboolean export_pdml_prefs_init = FALSE;
346 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
348 win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_pdml);
353 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
355 print_args_t *args = &export_pdml_args;
357 if (export_pdml_win != NULL) {
358 /* There's already a "Export pdml" dialog box; reactivate it. */
359 reactivate_window(export_pdml_win);
363 /* get settings from preferences (and other initial values) only once */
364 if(export_pdml_prefs_init == FALSE) {
365 export_pdml_prefs_init = TRUE;
366 args->format = PR_FMT_TEXT; /* XXX */
367 args->to_file = TRUE;
368 args->file = g_strdup("");
369 args->cmd = g_strdup("");
370 args->print_summary = TRUE;
371 args->print_dissections = print_dissections_as_displayed;
372 args->print_hex = FALSE;
373 args->print_formfeed = FALSE;
376 /* init the printing range */
377 packet_range_init(&args->range, &cfile);
378 args->range.process_filtered = TRUE;
380 export_pdml_win = open_print_dialog("Wireshark: Export as \"PDML\" file", output_action_export_pdml, args);
381 g_signal_connect(export_pdml_win, "destroy", G_CALLBACK(print_destroy_cb), &export_pdml_win);
386 * Keep a static pointer to the current "Export csv" window, if any, so that if
387 * somebody tries to do "File:Export to CSV" while there's already a "Export csv" window
388 * up, we just pop up the existing one, rather than creating a new one.
390 static GtkWidget *export_csv_win = NULL;
392 static print_args_t export_csv_args;
394 static gboolean export_csv_prefs_init = FALSE;
398 export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
400 win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_csv);
405 export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
407 print_args_t *args = &export_csv_args;
409 if (export_csv_win != NULL) {
410 /* There's already a "Export csv" dialog box; reactivate it. */
411 reactivate_window(export_csv_win);
415 /* get settings from preferences (and other initial values) only once */
416 if(export_csv_prefs_init == FALSE) {
417 export_csv_prefs_init = TRUE;
418 args->format = PR_FMT_TEXT; /* XXX */
419 args->to_file = TRUE;
420 args->file = g_strdup("");
421 args->cmd = g_strdup("");
422 args->print_summary = FALSE;
423 args->print_dissections = print_dissections_none;
424 args->print_hex = FALSE;
425 args->print_formfeed = FALSE;
428 /* init the printing range */
429 packet_range_init(&args->range, &cfile);
430 args->range.process_filtered = TRUE;
432 export_csv_win = open_print_dialog("Wireshark: Export as \"Comma Separated Values\" File", output_action_export_csv, args);
433 g_signal_connect(export_csv_win, "destroy", G_CALLBACK(print_destroy_cb), &export_csv_win);
438 * Keep a static pointer to the current "Export carrays" window, if any, so that if
439 * somebody tries to do "File:Export to carrays" while there's already a "Export carrays" window
440 * up, we just pop up the existing one, rather than creating a new one.
442 static GtkWidget *export_carrays_win = NULL;
444 static print_args_t export_carrays_args;
446 static gboolean export_carrays_prefs_init = FALSE;
450 export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
452 win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_carrays);
457 export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
459 print_args_t *args = &export_carrays_args;
461 if (export_carrays_win != NULL) {
462 /* There's already a "Export carrays" dialog box; reactivate it. */
463 reactivate_window(export_carrays_win);
467 /* get settings from preferences (and other initial values) only once */
468 if(export_carrays_prefs_init == FALSE) {
469 export_carrays_prefs_init = TRUE;
470 args->format = PR_FMT_TEXT;
471 args->to_file = TRUE;
472 args->file = g_strdup("");
473 args->cmd = g_strdup("");
474 args->print_summary = FALSE;
475 args->print_dissections = print_dissections_none;
476 args->print_hex = FALSE;
477 args->print_formfeed = FALSE;
480 /* init the printing range */
481 packet_range_init(&args->range, &cfile);
482 args->range.process_filtered = TRUE;
484 export_carrays_win = open_print_dialog("Wireshark: Export as \"C Arrays\" File",
485 output_action_export_carrays, args);
486 g_signal_connect(export_carrays_win, "destroy", G_CALLBACK(print_destroy_cb), &export_carrays_win);
491 print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
493 file_selection_browse(file_bt, file_te, "Wireshark: Print to File",
494 FILE_SELECTION_WRITE_BROWSE);
499 /* Open the print dialog */
501 open_print_dialog(const char *title, output_action_e action, print_args_t *args)
506 GtkWidget *printer_fr, *printer_vb, *export_format_lb;
507 GtkWidget *text_rb, *ps_rb, *pdml_rb, *psml_rb, *csv_rb, *carrays_rb;
508 GtkWidget *printer_grid, *dest_cb;
510 GtkWidget *cmd_lb, *cmd_te;
512 GtkWidget *file_bt, *file_te;
514 GtkWidget *range_fr, *range_grid;
516 GtkWidget *packet_hb;
518 GtkWidget *format_fr, *format_vb;
519 GtkWidget *summary_cb;
521 GtkWidget *details_cb;
522 GtkWidget *details_hb, *details_vb;
523 GtkWidget *collapse_all_rb, *as_displayed_rb, *expand_all_rb;
525 GtkWidget *sep, *formfeed_cb;
527 GtkWidget *bbox, *ok_bt, *cancel_bt, *help_bt;
530 main_win = dlg_window_new(title);
532 /* Vertical enclosing container for each row of widgets */
533 main_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
534 gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
535 gtk_container_add(GTK_CONTAINER(main_win), main_vb);
536 gtk_widget_show(main_vb);
538 /*****************************************************/
540 /*** printer frame ***/
541 printer_fr = gtk_frame_new(action == output_action_print ? "Printer" : "Export to file:");
542 gtk_box_pack_start(GTK_BOX(main_vb), printer_fr, TRUE, TRUE, 0);
543 gtk_widget_show(printer_fr);
545 printer_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
546 gtk_container_set_border_width(GTK_CONTAINER(printer_vb), 5);
547 gtk_container_add(GTK_CONTAINER(printer_fr), printer_vb);
548 gtk_widget_show(printer_vb);
550 /* "Plain text" / "Postscript" / "PDML", ... radio buttons */
551 text_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "Plain _text");
552 if (args->format == PR_FMT_TEXT)
553 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(text_rb), TRUE);
554 gtk_widget_set_tooltip_text(text_rb, "Print output in ascii \"plain text\" format. If you're unsure, use this format.");
555 gtk_box_pack_start(GTK_BOX(printer_vb), text_rb, FALSE, FALSE, 0);
556 if(action == output_action_print)
557 gtk_widget_show(text_rb);
559 ps_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "_PostScript");
560 if (args->format == PR_FMT_PS)
561 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps_rb), TRUE);
562 gtk_widget_set_tooltip_text(ps_rb, "Print output in \"postscript\" format, for postscript capable printers or print servers.");
563 gtk_box_pack_start(GTK_BOX(printer_vb), ps_rb, FALSE, FALSE, 0);
564 if(action == output_action_print)
565 gtk_widget_show(ps_rb);
567 pdml_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "PDM_L (XML: Packet Details Markup Language)");
568 if (action == output_action_export_pdml)
569 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdml_rb), TRUE);
570 gtk_widget_set_tooltip_text(pdml_rb,
571 "Print output in \"PDML\" (Packet Details Markup Language), "
572 "an XML based packet data interchange format. "
573 "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.");
574 gtk_box_pack_start(GTK_BOX(printer_vb), pdml_rb, FALSE, FALSE, 0);
575 /* gtk_widget_show(pdml_rb); */
577 psml_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "PSML (XML: Packet Summary Markup Language)");
578 if (action == output_action_export_psml)
579 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psml_rb), TRUE);
580 gtk_widget_set_tooltip_text(psml_rb,
581 "Print output in \"PSML\" (Packet Summary Markup Language), "
582 "an XML based packet summary interchange format. "
583 "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.");
584 gtk_box_pack_start(GTK_BOX(printer_vb), psml_rb, FALSE, FALSE, 0);
585 /* gtk_widget_show(psml_rb); */
587 csv_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "_CSV");
588 if (action == output_action_export_csv)
589 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(csv_rb), TRUE);
590 gtk_widget_set_tooltip_text(csv_rb,
591 "Print output in \"Comma Separated Values\" (CSV) format, "
592 "a text format compatible with OpenOffice and Excel. "
593 "One row for each packet, with its timestamp and size.");
594 gtk_box_pack_start(GTK_BOX(printer_vb), csv_rb, FALSE, FALSE, 0);
595 /* gtk_widget_show(csv_rb); */
597 carrays_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "C Arrays");
598 if (action == output_action_export_carrays)
599 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(carrays_rb), TRUE);
600 gtk_widget_set_tooltip_text(carrays_rb,
601 "Print output in C Arrays format, "
602 "a text file suitable for use in C/C++ programs. "
603 "One char[] for each packet.");
604 gtk_box_pack_start(GTK_BOX(printer_vb), carrays_rb, FALSE, FALSE, 0);
605 /* gtk_widget_show(carrays_rb); */
608 printer_grid = ws_gtk_grid_new();
609 gtk_box_pack_start(GTK_BOX(printer_vb), printer_grid, FALSE, FALSE, 0);
611 ws_gtk_grid_set_row_spacing(GTK_GRID(printer_grid), 5);
612 ws_gtk_grid_set_column_spacing(GTK_GRID(printer_grid), 5);
613 gtk_widget_show(printer_grid);
616 /* Output to file button */
617 dest_cb = gtk_check_button_new_with_mnemonic("Output to _file:");
619 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
620 gtk_widget_set_tooltip_text(dest_cb, "Output to file instead of printer");
621 ws_gtk_grid_attach_extended(GTK_GRID(printer_grid), dest_cb, 0, 0, 1, 1, 0, 0, 0, 0);
622 if(action == output_action_print)
623 gtk_widget_show(dest_cb);
625 /* File text entry */
626 file_te = gtk_entry_new();
627 g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_TE_KEY, file_te);
628 gtk_widget_set_tooltip_text(file_te, "Enter Output filename");
629 gtk_entry_set_text(GTK_ENTRY(file_te), args->file);
630 ws_gtk_grid_attach_extended(GTK_GRID(printer_grid), file_te, 1, 0, 1, 1, GTK_EXPAND|GTK_FILL, 0, 0, 0);
631 gtk_widget_set_sensitive(file_te, args->to_file);
632 gtk_widget_show(file_te);
634 gtk_widget_grab_focus(file_te);
636 /* "Browse" button */
637 file_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
638 g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_BT_KEY, file_bt);
639 g_object_set_data(G_OBJECT(file_bt), PRINT_TE_PTR_KEY, file_te);
640 gtk_widget_set_tooltip_text(file_bt, "Browse output filename in filesystem");
641 ws_gtk_grid_attach_extended(GTK_GRID(printer_grid), file_bt, 2, 0, 1, 1, 0, 0, 0, 0);
642 gtk_widget_set_sensitive(file_bt, args->to_file);
643 gtk_widget_show(file_bt);
645 /* Command label and text entry */
647 cmd_lb = gtk_label_new("Print command:");
648 g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_LB_KEY, cmd_lb);
649 gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0f, 0.5f);
650 ws_gtk_grid_attach_extended(GTK_GRID(printer_grid), cmd_lb, 0, 1, 1, 1, 0, 0, 0, 0);
651 gtk_widget_set_sensitive(cmd_lb, !args->to_file);
652 if(action == output_action_print)
653 gtk_widget_show(cmd_lb);
655 cmd_te = gtk_entry_new();
656 g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_TE_KEY, cmd_te);
657 gtk_widget_set_tooltip_text(cmd_te, "Enter print command");
658 gtk_entry_set_text(GTK_ENTRY(cmd_te), args->cmd);
659 ws_gtk_grid_attach_extended(GTK_GRID(printer_grid), cmd_te, 1, 1, 1, 1, 0, 0, 0, 0);
660 gtk_widget_set_sensitive(cmd_te, !args->to_file);
661 if(action == output_action_print)
662 gtk_widget_show(cmd_te);
665 g_signal_connect(dest_cb, "toggled", G_CALLBACK(print_cmd_toggle_dest), NULL);
666 g_signal_connect(file_bt, "clicked", G_CALLBACK(print_browse_file_cb), file_te);
668 if(action == output_action_export_ps) {
669 export_format_lb = gtk_label_new("(PostScript files can be easily converted to PDF files using ghostscript's ps2pdf)");
670 gtk_box_pack_start(GTK_BOX(printer_vb), export_format_lb, FALSE, FALSE, 0);
671 gtk_widget_show(export_format_lb);
674 /*****************************************************/
676 /*** hor box for range and format frames ***/
677 packet_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5, FALSE);
678 gtk_box_pack_start(GTK_BOX(main_vb), packet_hb, TRUE, TRUE, 0);
679 gtk_widget_show(packet_hb);
681 /*** packet range frame ***/
682 range_fr = gtk_frame_new("Packet Range");
683 gtk_box_pack_start(GTK_BOX(packet_hb), range_fr, FALSE, FALSE, 0);
684 gtk_widget_show(range_fr);
686 range_grid = range_new(&args->range, FALSE);
687 gtk_container_add(GTK_CONTAINER(range_fr), range_grid);
688 gtk_widget_show(range_grid);
690 /*****************************************************/
692 /*** packet format frame ***/
693 format_fr = gtk_frame_new("Packet Format");
694 gtk_box_pack_start(GTK_BOX(packet_hb), format_fr, TRUE, TRUE, 0);
695 if( action == output_action_print ||
696 action == output_action_export_text ||
697 action == output_action_export_ps)
698 gtk_widget_show(format_fr);
699 format_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 5, FALSE);
700 gtk_container_set_border_width(GTK_CONTAINER(format_vb), 5);
701 gtk_container_add(GTK_CONTAINER(format_fr), format_vb);
702 gtk_widget_show(format_vb);
704 /* "Print summary line" check button */
705 summary_cb = gtk_check_button_new_with_mnemonic("Packet summary line");
706 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(summary_cb), args->print_summary);
707 g_signal_connect(summary_cb, "clicked", G_CALLBACK(print_cmd_toggle_detail), main_win);
708 gtk_widget_set_tooltip_text(summary_cb, "Output of a packet summary line, like in the packet list");
709 gtk_box_pack_start(GTK_BOX(format_vb), summary_cb, TRUE, TRUE, 0);
710 gtk_widget_show(summary_cb);
713 /* "Details" check button */
714 details_cb = gtk_check_button_new_with_mnemonic("Packet details:");
715 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(details_cb), args->print_dissections != print_dissections_none);
716 g_signal_connect(details_cb, "clicked", G_CALLBACK(print_cmd_toggle_detail), main_win);
717 gtk_widget_set_tooltip_text(details_cb, "Output format of the selected packet details (protocol tree).");
718 gtk_box_pack_start(GTK_BOX(format_vb), details_cb, TRUE, TRUE, 0);
719 gtk_widget_show(details_cb);
721 /*** packet details ***/
722 details_hb = ws_gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6, FALSE);
723 gtk_container_set_border_width(GTK_CONTAINER(details_hb), 0);
724 gtk_box_pack_start(GTK_BOX(format_vb), details_hb, TRUE, TRUE, 0);
725 gtk_widget_show(details_hb);
727 details_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
728 gtk_container_set_border_width(GTK_CONTAINER(details_vb), 0);
729 gtk_box_pack_start(GTK_BOX(details_hb), details_vb, FALSE, FALSE, 10);
730 gtk_widget_show(details_vb);
732 details_vb = ws_gtk_box_new(GTK_ORIENTATION_VERTICAL, 6, FALSE);
733 gtk_container_set_border_width(GTK_CONTAINER(details_vb), 0);
734 gtk_box_pack_start(GTK_BOX(details_hb), details_vb, FALSE, FALSE, 0);
735 gtk_widget_show(details_vb);
737 /* "All collapsed"/"As displayed"/"All Expanded" radio buttons */
738 collapse_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "All co_llapsed");
739 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(collapse_all_rb), args->print_dissections == print_dissections_collapsed);
740 gtk_widget_set_tooltip_text(collapse_all_rb, "Output of the packet details tree \"collapsed\"");
741 gtk_box_pack_start(GTK_BOX(details_vb), collapse_all_rb, TRUE, TRUE, 0);
742 gtk_widget_show(collapse_all_rb);
744 as_displayed_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(collapse_all_rb), "As displa_yed");
745 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(as_displayed_rb), args->print_dissections == print_dissections_as_displayed);
746 gtk_widget_set_tooltip_text(as_displayed_rb, "Output of the packet details tree \"as displayed\"");
747 gtk_box_pack_start(GTK_BOX(details_vb), as_displayed_rb, TRUE, TRUE, 0);
748 gtk_widget_show(as_displayed_rb);
750 expand_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(collapse_all_rb), "All e_xpanded");
751 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(expand_all_rb), args->print_dissections == print_dissections_expanded);
752 gtk_widget_set_tooltip_text(expand_all_rb, "Output of the packet details tree \"expanded\"");
753 gtk_box_pack_start(GTK_BOX(details_vb), expand_all_rb, TRUE, TRUE, 0);
754 gtk_widget_show(expand_all_rb);
756 /* "Print hex" check button. */
757 hex_cb = gtk_check_button_new_with_mnemonic("Packet bytes");
758 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_cb), args->print_hex);
759 g_signal_connect(hex_cb, "clicked", G_CALLBACK(print_cmd_toggle_detail), main_win);
760 gtk_widget_set_tooltip_text(hex_cb, "Add a hexdump of the packet data");
761 gtk_box_pack_start(GTK_BOX(format_vb), hex_cb, TRUE, TRUE, 0);
762 gtk_widget_show(hex_cb);
765 sep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
766 gtk_box_pack_start(GTK_BOX(format_vb), sep, TRUE, TRUE, 0);
767 gtk_widget_show(sep);
769 /* "Each packet on a new page" check button. */
770 formfeed_cb = gtk_check_button_new_with_mnemonic("Each packet on a new page");
771 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(formfeed_cb), args->print_formfeed);
772 gtk_widget_set_tooltip_text (formfeed_cb, "When checked, a new page will be used for each packet. "
773 "This is done by adding a formfeed (or similar) between the packet outputs.");
774 gtk_box_pack_start(GTK_BOX(format_vb), formfeed_cb, TRUE, TRUE, 0);
775 gtk_widget_show(formfeed_cb);
778 g_object_set_data(G_OBJECT(main_win), PRINT_ARGS_KEY, args);
779 g_object_set_data(G_OBJECT(main_win), PRINT_SUMMARY_CB_KEY, summary_cb);
780 g_object_set_data(G_OBJECT(main_win), PRINT_DETAILS_CB_KEY, details_cb);
781 g_object_set_data(G_OBJECT(main_win), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
782 g_object_set_data(G_OBJECT(main_win), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
783 g_object_set_data(G_OBJECT(main_win), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
784 g_object_set_data(G_OBJECT(main_win), PRINT_HEX_CB_KEY, hex_cb);
786 /*****************************************************/
790 bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
791 gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
792 gtk_widget_show(bbox);
794 ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK);
796 g_object_set_data(G_OBJECT(main_win), PRINT_BT_KEY, ok_bt);
798 g_object_set_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY, ps_rb);
799 g_object_set_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY, pdml_rb);
800 g_object_set_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY, psml_rb);
801 g_object_set_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY, csv_rb);
802 g_object_set_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY, carrays_rb);
803 g_object_set_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY, dest_cb);
805 g_object_set_data(G_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
808 g_object_set_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY, args);
809 g_object_set_data(G_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
810 g_object_set_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY, summary_cb);
811 g_object_set_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY, details_cb);
812 g_object_set_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
813 g_object_set_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
814 g_object_set_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
815 g_object_set_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY, hex_cb);
816 g_object_set_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY, formfeed_cb);
817 g_signal_connect(ok_bt, "clicked", G_CALLBACK(print_ok_cb), main_win);
818 gtk_widget_set_tooltip_text (ok_bt, "Start output");
820 cancel_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
821 window_set_cancel_button(main_win, cancel_bt, window_cancel_button_cb);
822 gtk_widget_set_tooltip_text (cancel_bt, "Cancel and exit dialog");
824 if(action == output_action_print) {
825 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
826 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PRINT_DIALOG);
829 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
830 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_EXPORT_FILE_WIN32_DIALOG);
832 help_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
833 g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_EXPORT_FILE_DIALOG);
837 gtk_widget_grab_default(ok_bt);
839 /* Catch the "activate" signal on the "Command" and "File" text entries,
840 so that if the user types Return there, we act as if the "OK" button
841 had been selected, as happens if Return is typed if some widget
842 that *doesn't* handle the Return key has the input focus. */
844 dlg_set_activate(cmd_te, ok_bt);
846 if(action != output_action_print)
847 dlg_set_activate(file_te, ok_bt);
849 g_signal_connect(main_win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
851 gtk_widget_show(main_win);
852 window_present(main_win);
858 /* user changed "print to" destination */
860 print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
863 GtkWidget *cmd_lb, *cmd_te;
865 GtkWidget *file_bt, *file_te;
869 cmd_lb = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_LB_KEY));
870 cmd_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_TE_KEY));
872 file_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_BT_KEY));
873 file_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_TE_KEY));
875 to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
877 gtk_widget_set_sensitive(cmd_lb, !to_file);
878 gtk_widget_set_sensitive(cmd_te, !to_file);
880 gtk_widget_set_sensitive(file_bt, to_file);
881 gtk_widget_set_sensitive(file_te, to_file);
885 /* user changed "packet details" */
887 print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
889 GtkWidget *print_bt, *summary_cb, *details_cb, *collapse_all_rb, *expand_all_rb, *as_displayed_rb, *hex_cb;
890 gboolean print_detail;
892 print_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_BT_KEY));
893 summary_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_SUMMARY_CB_KEY));
894 details_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_DETAILS_CB_KEY));
895 collapse_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_COLLAPSE_ALL_RB_KEY));
896 as_displayed_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_AS_DISPLAYED_RB_KEY));
897 expand_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_EXPAND_ALL_RB_KEY));
898 hex_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_HEX_CB_KEY));
900 /* is user disabled details, disable the corresponding buttons */
901 print_detail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb));
902 gtk_widget_set_sensitive(collapse_all_rb, print_detail);
903 gtk_widget_set_sensitive(as_displayed_rb, print_detail);
904 gtk_widget_set_sensitive(expand_all_rb, print_detail);
906 /* if user selected nothing to print at all, disable the "ok" button */
907 gtk_widget_set_sensitive(print_bt,
908 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (summary_cb)) ||
909 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb)) ||
910 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_cb)));
915 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
922 gboolean export_as_pdml = FALSE, export_as_psml = FALSE;
923 gboolean export_as_csv = FALSE;
924 gboolean export_as_carrays = FALSE;
926 gboolean win_printer = FALSE;
929 char *tmp_oldfile = NULL;
931 cf_print_status_t status;
933 args = (print_args_t *)g_object_get_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY);
935 /* Check whether the range is valid. */
936 if (!range_check_validity(&args->range)) {
937 /* The range isn't valid; don't dismiss the print/export dialog box,
938 just leave it around so that the user can, after they
939 dismiss the alert box popped up for the error, try again. */
943 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY);
944 args->to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
947 g_dest = gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
948 PRINT_FILE_TE_KEY)));
950 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
951 "Output to file, but no file specified.");
955 args->file = g_strdup(g_dest);
956 /* Save the directory name for future file dialogs. */
957 f_name = g_strdup(g_dest);
958 dirname = get_dirname(f_name); /* Overwrites f_name */
959 set_last_open_dir(dirname);
964 /* We currently don't have a function in util.h to create just a tempfile */
965 /* name, so simply create a tempfile using the "official" function, */
966 /* then delete this file again. After this, the name MUST be available. */
968 /* Don't use tmpnam() or such, as this will fail under some ACL */
969 /* circumstances: http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=358 */
970 /* Also: tmpnam is "insecure" and should not be used. */
971 tmp_fd = create_tempfile(&tmp_namebuf, "wshprint");
973 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
974 "Couldn't create a temporary file for printing:\n%s", tmp_namebuf);
977 /* remember to restore these values later! */
978 tmp_oldfile = args->file;
979 args->file = g_strdup(tmp_namebuf);
980 ws_unlink(args->file);
981 args->to_file = TRUE;
984 args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
985 PRINT_CMD_TE_KEY))));
989 args->format = PR_FMT_TEXT;
990 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY);
991 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
992 args->format = PR_FMT_PS;
993 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY);
994 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
995 export_as_pdml = TRUE;
996 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY);
997 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
998 export_as_psml = TRUE;
999 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY);
1000 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
1001 export_as_csv = TRUE;
1002 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY);
1003 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
1004 export_as_carrays = TRUE;
1006 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY);
1007 args->print_summary = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1009 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY);
1010 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1011 args->print_dissections = print_dissections_collapsed;
1013 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY);
1014 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1015 args->print_dissections = print_dissections_as_displayed;
1017 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY);
1018 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1019 args->print_dissections = print_dissections_expanded;
1022 /* the details setting has priority over the radio buttons */
1023 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY);
1024 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1025 args->print_dissections = print_dissections_none;
1028 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY);
1029 args->print_hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1031 button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY);
1032 args->print_formfeed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1035 window_destroy(GTK_WIDGET(parent_w));
1037 /* Now print/export the packets */
1039 status = cf_write_pdml_packets(&cfile, args);
1040 else if (export_as_psml)
1041 status = cf_write_psml_packets(&cfile, args);
1042 else if (export_as_csv)
1043 status = cf_write_csv_packets(&cfile, args);
1044 else if (export_as_carrays)
1045 status = cf_write_carrays_packets(&cfile, args);
1047 switch (args->format) {
1050 if (args->to_file) {
1051 args->stream = print_stream_text_new(TRUE, args->file);
1052 if (args->stream == NULL) {
1053 open_failure_alert_box(args->file, errno, TRUE);
1057 args->stream = print_stream_text_new(FALSE, args->cmd);
1058 if (args->stream == NULL) {
1059 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1060 "Couldn't run print command %s.", args->cmd);
1066 if (args->to_file) {
1067 args->stream = print_stream_ps_new(TRUE, args->file);
1068 if (args->stream == NULL) {
1069 open_failure_alert_box(args->file, errno, TRUE);
1073 args->stream = print_stream_ps_new(FALSE, args->cmd);
1074 if (args->stream == NULL) {
1075 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1076 "Couldn't run print command %s.", args->cmd);
1082 g_assert_not_reached();
1085 status = cf_print_packets(&cfile, args);
1092 case CF_PRINT_OPEN_ERROR:
1094 open_failure_alert_box(args->file, errno, TRUE);
1096 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't run print command %s.",
1100 case CF_PRINT_WRITE_ERROR:
1102 write_failure_alert_box(args->file, errno);
1104 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1105 "Error writing to print command: %s", g_strerror(errno));
1111 print_mswin(args->file);
1113 /* trash temp file */
1114 ws_remove(args->file);
1117 /* restore old settings */
1118 args->to_file = FALSE;
1119 args->file = tmp_oldfile;
1125 print_destroy_cb(GtkWidget *win, gpointer user_data)
1129 /* Is there a file selection dialog associated with this
1130 Print File dialog? */
1131 fs = (GtkWidget *)g_object_get_data(G_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
1134 /* Yes. Destroy it. */
1138 /* Note that we no longer have a "Print" dialog box. */
1139 *((gpointer *) user_data) = NULL;