From beroset:
[metze/wireshark/wip.git] / ui / gtk / print_dlg.c
1 /* print_dlg.c
2  * Dialog boxes for printing and exporting to text files
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #include "config.h"
26
27 #include <string.h>
28
29 #include <gtk/gtk.h>
30
31 #include <epan/prefs.h>
32 #include <epan/epan_dissect.h>
33 #include <epan/filesystem.h>
34
35 #include "print.h"
36 #include "ui/alert_box.h"
37 #include "ui/simple_dialog.h"
38 #include "ui/util.h"
39 #include <wsutil/file_util.h>
40
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"
50
51 #ifdef _WIN32
52 #include <gdk/gdkwin32.h>
53 #include <windows.h>
54 #include "ui/win32/file_dlg_win32.h"
55 #include "ui/win32/print_win32.h"
56 #include "tempfile.h"
57 #endif
58
59 /* dialog output action */
60 typedef enum {
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 */
68 } output_action_e;
69
70
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.
75
76   Eventually, we should try to use the native Win32 printing API
77   for this (and also use various UNIX printing APIs, when present?).
78 */
79
80 static GtkWidget *
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);
86
87
88
89 #define PRINT_ARGS_KEY            "printer_args"
90
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"
97
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"
105
106 #define PRINT_BT_KEY              "printer_button"
107
108 #define PRINT_TE_PTR_KEY          "printer_file_te_ptr"
109
110
111 /*
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.
115  */
116 static GtkWidget *print_win = NULL;
117
118 static print_args_t  print_args;
119
120 static gboolean print_prefs_init = FALSE;
121
122
123 static void
124 file_print_cmd(gboolean print_selected)
125 {
126   print_args_t *args = &print_args;
127
128   if (print_win != NULL) {
129     /* There's already a "Print" dialog box; reactivate it. */
130     reactivate_window(print_win);
131     return;
132   }
133
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;
145   }
146
147   /* init the printing range */
148   packet_range_init(&args->range, &cfile);
149   args->range.process_filtered = TRUE;
150
151   if(print_selected) {
152       args->range.process = range_process_selected;
153   }
154
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);
157 }
158
159 void
160 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
161 {
162   file_print_cmd(FALSE);
163 }
164
165 void
166 file_print_selected_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
167 {
168   file_print_cmd(TRUE);
169 }
170
171 /*
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.
175  */
176 static GtkWidget *export_text_win = NULL;
177
178 static print_args_t  export_text_args;
179
180 static gboolean export_text_prefs_init = FALSE;
181
182
183 #ifdef _WIN32
184 void
185 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
186 {
187   win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_text);
188   return;
189 }
190 #else
191 void
192 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
193 {
194   print_args_t *args = &export_text_args;
195
196   if (export_text_win != NULL) {
197     /* There's already a "Export text" dialog box; reactivate it. */
198     reactivate_window(export_text_win);
199     return;
200   }
201
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;
213   }
214
215   /* init the printing range */
216   packet_range_init(&args->range, &cfile);
217   args->range.process_filtered = TRUE;
218
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);
221 }
222 #endif
223
224
225 /*
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.
229  */
230 static GtkWidget *export_ps_win = NULL;
231
232 static print_args_t  export_ps_args;
233
234 static gboolean export_ps_prefs_init = FALSE;
235
236
237 #ifdef _WIN32
238 void
239 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
240 {
241   win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_ps);
242   return;
243 }
244 #else
245 void
246 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
247 {
248   print_args_t *args = &export_ps_args;
249
250   if (export_ps_win != NULL) {
251     /* There's already a "Export ps" dialog box; reactivate it. */
252     reactivate_window(export_ps_win);
253     return;
254   }
255
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;
267   }
268
269   /* init the printing range */
270   packet_range_init(&args->range, &cfile);
271   args->range.process_filtered = TRUE;
272
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);
275 }
276 #endif
277
278
279 /*
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.
283  */
284 static GtkWidget *export_psml_win = NULL;
285
286 static print_args_t  export_psml_args;
287
288 static gboolean export_psml_prefs_init = FALSE;
289
290
291 #ifdef _WIN32
292 void
293 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
294 {
295   win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_psml);
296   return;
297 }
298 #else
299 void
300 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
301 {
302   print_args_t *args = &export_psml_args;
303
304   if (export_psml_win != NULL) {
305     /* There's already a "Export psml" dialog box; reactivate it. */
306     reactivate_window(export_psml_win);
307     return;
308   }
309
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;
321   }
322
323   /* init the printing range */
324   packet_range_init(&args->range, &cfile);
325   args->range.process_filtered = TRUE;
326
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);
329 }
330 #endif
331
332 /*
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.
336  */
337 static GtkWidget *export_pdml_win = NULL;
338
339 static print_args_t  export_pdml_args;
340
341 static gboolean export_pdml_prefs_init = FALSE;
342
343
344 #ifdef _WIN32
345 void
346 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
347 {
348   win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_pdml);
349   return;
350 }
351 #else
352 void
353 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
354 {
355   print_args_t *args = &export_pdml_args;
356
357   if (export_pdml_win != NULL) {
358     /* There's already a "Export pdml" dialog box; reactivate it. */
359     reactivate_window(export_pdml_win);
360     return;
361   }
362
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;
374   }
375
376   /* init the printing range */
377   packet_range_init(&args->range, &cfile);
378   args->range.process_filtered = TRUE;
379
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);
382 }
383 #endif
384
385 /*
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.
389  */
390 static GtkWidget *export_csv_win = NULL;
391
392 static print_args_t  export_csv_args;
393
394 static gboolean export_csv_prefs_init = FALSE;
395
396 #ifdef _WIN32
397 void
398 export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
399 {
400   win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_csv);
401   return;
402 }
403 #else
404 void
405 export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
406 {
407   print_args_t *args = &export_csv_args;
408
409   if (export_csv_win != NULL) {
410     /* There's already a "Export csv" dialog box; reactivate it. */
411     reactivate_window(export_csv_win);
412     return;
413   }
414
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;
426   }
427
428   /* init the printing range */
429   packet_range_init(&args->range, &cfile);
430   args->range.process_filtered = TRUE;
431
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);
434 }
435 #endif
436
437 /*
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.
441  */
442 static GtkWidget *export_carrays_win = NULL;
443
444 static print_args_t export_carrays_args;
445
446 static gboolean export_carrays_prefs_init = FALSE;
447
448 #ifdef _WIN32
449 void
450 export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
451 {
452   win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), &cfile, export_type_carrays);
453   return;
454 }
455 #else
456 void
457 export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
458 {
459   print_args_t *args = &export_carrays_args;
460
461   if (export_carrays_win != NULL) {
462     /* There's already a "Export carrays" dialog box; reactivate it. */
463     reactivate_window(export_carrays_win);
464     return;
465   }
466
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;
478   }
479
480   /* init the printing range */
481   packet_range_init(&args->range, &cfile);
482   args->range.process_filtered = TRUE;
483
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);
487 }
488 #endif
489
490 static void
491 print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
492 {
493     file_selection_browse(file_bt, file_te, "Wireshark: Print to File",
494                           FILE_SELECTION_WRITE_BROWSE);
495 }
496
497
498
499 /* Open the print dialog */
500 static GtkWidget *
501 open_print_dialog(const char *title, output_action_e action, print_args_t *args)
502 {
503   GtkWidget *main_win;
504   GtkWidget *main_vb;
505
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;
509 #ifndef _WIN32
510   GtkWidget *cmd_lb, *cmd_te;
511 #endif
512   GtkWidget *file_bt, *file_te;
513
514   GtkWidget *range_fr, *range_grid;
515
516   GtkWidget *packet_hb;
517
518   GtkWidget *format_fr, *format_vb;
519   GtkWidget *summary_cb;
520
521   GtkWidget *details_cb;
522   GtkWidget *details_hb, *details_vb;
523   GtkWidget *collapse_all_rb, *as_displayed_rb, *expand_all_rb;
524   GtkWidget *hex_cb;
525   GtkWidget *sep, *formfeed_cb;
526
527   GtkWidget *bbox, *ok_bt, *cancel_bt, *help_bt;
528
529   /* dialog window */
530   main_win = dlg_window_new(title);
531
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);
537
538 /*****************************************************/
539
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);
544
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);
549
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);
558
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);
566
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); */
576
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); */
586
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); */
596
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); */
606
607   /* printer grid */
608   printer_grid = ws_gtk_grid_new();
609   gtk_box_pack_start(GTK_BOX(printer_vb), printer_grid, FALSE, FALSE, 0);
610
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);
614
615
616   /* Output to file button */
617   dest_cb = gtk_check_button_new_with_mnemonic("Output to _file:");
618   if (args->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);
624
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);
633   if (args->to_file)
634     gtk_widget_grab_focus(file_te);
635
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);
644
645   /* Command label and text entry */
646 #ifndef _WIN32
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);
654
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);
663 #endif
664
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);
667
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);
672   }
673
674 /*****************************************************/
675
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);
680
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);
685
686   range_grid = range_new(&args->range, FALSE);
687   gtk_container_add(GTK_CONTAINER(range_fr), range_grid);
688   gtk_widget_show(range_grid);
689
690 /*****************************************************/
691
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);
703
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);
711
712
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);
720
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);
726
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);
731
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);
736
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);
743
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);
749
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);
755
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);
763
764   /* separator */
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);
768
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);
776
777
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);
785
786 /*****************************************************/
787
788
789   /* Button row */
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);
793
794   ok_bt = (GtkWidget *)g_object_get_data(G_OBJECT(bbox), action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK);
795
796   g_object_set_data(G_OBJECT(main_win), PRINT_BT_KEY, ok_bt);
797
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);
804 #ifndef _WIN32
805   g_object_set_data(G_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
806 #endif
807
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");
819
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");
823
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);
827   } else {
828 #ifdef _WIN32
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);
831 #else
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);
834 #endif
835   }
836
837   gtk_widget_grab_default(ok_bt);
838
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. */
843 #ifndef _WIN32
844   dlg_set_activate(cmd_te, ok_bt);
845 #endif
846   if(action != output_action_print)
847     dlg_set_activate(file_te, ok_bt);
848
849   g_signal_connect(main_win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
850
851   gtk_widget_show(main_win);
852   window_present(main_win);
853
854   return main_win;
855 }
856
857
858 /* user changed "print to" destination */
859 static void
860 print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
861 {
862 #ifndef _WIN32
863   GtkWidget *cmd_lb, *cmd_te;
864 #endif
865   GtkWidget *file_bt, *file_te;
866   int        to_file;
867
868 #ifndef _WIN32
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));
871 #endif
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));
874
875   to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
876 #ifndef _WIN32
877   gtk_widget_set_sensitive(cmd_lb, !to_file);
878   gtk_widget_set_sensitive(cmd_te, !to_file);
879 #endif
880   gtk_widget_set_sensitive(file_bt, to_file);
881   gtk_widget_set_sensitive(file_te, to_file);
882 }
883
884
885 /* user changed "packet details" */
886 static void
887 print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
888 {
889   GtkWidget *print_bt, *summary_cb, *details_cb, *collapse_all_rb, *expand_all_rb, *as_displayed_rb, *hex_cb;
890   gboolean   print_detail;
891
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));
899
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);
905
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)));
911 }
912
913
914 static void
915 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
916 {
917   GtkWidget         *button;
918   print_args_t      *args;
919   const gchar       *g_dest;
920   gchar             *f_name;
921   gchar             *dirname;
922   gboolean           export_as_pdml    = FALSE, export_as_psml = FALSE;
923   gboolean           export_as_csv     = FALSE;
924   gboolean           export_as_carrays = FALSE;
925 #ifdef _WIN32
926   gboolean           win_printer       = FALSE;
927   int                tmp_fd;
928   char              *tmp_namebuf;
929   char              *tmp_oldfile       = NULL;
930 #endif
931   cf_print_status_t  status;
932
933   args = (print_args_t *)g_object_get_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY);
934
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. */
940     return;
941   }
942
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));
945
946   if (args->to_file) {
947     g_dest = gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
948                                                             PRINT_FILE_TE_KEY)));
949     if (!g_dest[0]) {
950       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
951         "Output to file, but no file specified.");
952       return;
953     }
954     g_free(args->file);
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);
960     g_free(f_name);
961   } else {
962 #ifdef _WIN32
963     win_printer = TRUE;
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.   */
967     /* */
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");
972     if(tmp_fd == -1) {
973       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
974                     "Couldn't create a temporary file for printing:\n%s", tmp_namebuf);
975       return;
976     }
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;
982 #else
983     g_free(args->cmd);
984     args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
985       PRINT_CMD_TE_KEY))));
986 #endif
987   }
988
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;
1005
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));
1008
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;
1012   }
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;
1016   }
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;
1020   }
1021
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;
1026   }
1027
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));
1030
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));
1033
1034
1035   window_destroy(GTK_WIDGET(parent_w));
1036
1037   /* Now print/export the packets */
1038   if (export_as_pdml)
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);
1046   else {
1047     switch (args->format) {
1048
1049     case PR_FMT_TEXT:
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);
1054           return;
1055         }
1056       } else {
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);
1061         }
1062       }
1063       break;
1064
1065     case PR_FMT_PS:
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);
1070           return;
1071         }
1072       } else {
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);
1077         }
1078       }
1079       break;
1080
1081     default:
1082       g_assert_not_reached();
1083       return;
1084     }
1085     status = cf_print_packets(&cfile, args);
1086   }
1087   switch (status) {
1088
1089   case CF_PRINT_OK:
1090     break;
1091
1092   case CF_PRINT_OPEN_ERROR:
1093     if (args->to_file)
1094       open_failure_alert_box(args->file, errno, TRUE);
1095     else
1096       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't run print command %s.",
1097         args->cmd);
1098     break;
1099
1100   case CF_PRINT_WRITE_ERROR:
1101     if (args->to_file)
1102       write_failure_alert_box(args->file, errno);
1103     else
1104       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1105                     "Error writing to print command: %s", g_strerror(errno));
1106     break;
1107   }
1108
1109 #ifdef _WIN32
1110   if (win_printer) {
1111     print_mswin(args->file);
1112
1113     /* trash temp file */
1114     ws_remove(args->file);
1115     g_free(args->file);
1116
1117     /* restore old settings */
1118     args->to_file = FALSE;
1119     args->file = tmp_oldfile;
1120   }
1121 #endif
1122 }
1123
1124 static void
1125 print_destroy_cb(GtkWidget *win, gpointer user_data)
1126 {
1127   GtkWidget *fs;
1128
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);
1132
1133   if (fs != NULL) {
1134     /* Yes.  Destroy it. */
1135     window_destroy(fs);
1136   }
1137
1138   /* Note that we no longer have a "Print" dialog box. */
1139   *((gpointer *) user_data) = NULL;
1140 }