replace CHECK_BUTTON_NEW_WITH_MNEMONIC with gtk_check_button_new_with_mnemonic
[obnox/wireshark/wip.git] / 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30
31 #include <gtk/gtk.h>
32
33 #include "globals.h"
34 #include "gtkglobals.h"
35 #include "keys.h"
36 #include "print.h"
37 #include <epan/prefs.h>
38 #include "alert_box.h"
39 #include "simple_dialog.h"
40 #include "capture_file_dlg.h"
41 #include "gui_utils.h"
42 #include "dlg_utils.h"
43 #include "file_dlg.h"
44 #include "main.h"
45 #include <epan/epan_dissect.h>
46 #include <epan/filesystem.h>
47 #ifdef _WIN32
48 #include "print_mswin.h"
49 #endif
50 #include "compat_macros.h"
51 #include "range_utils.h"
52 #include "help_dlg.h"
53 #include "file_util.h"
54 #include "tempfile.h"
55 #include "util.h"
56
57 #if _WIN32
58 #include <gdk/gdkwin32.h>
59 #include <windows.h>
60 #include "win32-file-dlg.h"
61 #endif
62
63 /* dialog output action */
64 typedef enum {
65   output_action_print,          /* print text to printer */
66   output_action_export_text,    /* export to plain text */
67   output_action_export_ps,      /* export to postscript */
68   output_action_export_psml,    /* export to packet summary markup language */
69   output_action_export_pdml,    /* export to packet data markup language */
70   output_action_export_csv,     /* export to csv file */
71   output_action_export_carrays  /* export to C array file */
72 } output_action_e;
73
74
75 /* On Win32, a GUI application apparently can't use "popen()" (it
76   "returns an invalid file handle, if used in a Windows program,
77   that will cause the program to hang indefinitely"), so we can't
78   use a pipe to a print command to print to a printer.
79
80   Eventually, we should try to use the native Win32 printing API
81   for this (and also use various UNIX printing APIs, when present?).
82 */
83
84 static GtkWidget *
85 open_print_dialog(const char *title, output_action_e action, print_args_t *args);
86 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
87 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
88 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
89 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
90
91
92
93 #define PRINT_ARGS_KEY            "printer_args"
94
95 #define PRINT_PS_RB_KEY           "printer_ps_radio_button"
96 #define PRINT_PDML_RB_KEY         "printer_pdml_radio_button"
97 #define PRINT_PSML_RB_KEY         "printer_psml_radio_button"
98 #define PRINT_CSV_RB_KEY          "printer_csv_radio_button"
99 #define PRINT_CARRAYS_RB_KEY      "printer_carrays_radio_button"
100 #define PRINT_DEST_CB_KEY         "printer_destination_check_button"
101
102 #define PRINT_SUMMARY_CB_KEY      "printer_summary_check_button"
103 #define PRINT_DETAILS_CB_KEY      "printer_details_check_button"
104 #define PRINT_COLLAPSE_ALL_RB_KEY "printer_collapse_all_radio_button"
105 #define PRINT_AS_DISPLAYED_RB_KEY "printer_as_displayed_radio_button"
106 #define PRINT_EXPAND_ALL_RB_KEY   "printer_expand_all_radio_button"
107 #define PRINT_HEX_CB_KEY          "printer_hex_check_button"
108 #define PRINT_FORMFEED_CB_KEY     "printer_formfeed_check_button"
109
110 #define PRINT_BT_KEY              "printer_button"
111
112 #define PRINT_TE_PTR_KEY          "printer_file_te_ptr"
113
114
115 /*
116  * Keep a static pointer to the current "Print" window, if any, so that if
117  * somebody tries to do "File:Print" while there's already a "Print" window
118  * up, we just pop up the existing one, rather than creating a new one.
119  */
120 static GtkWidget *print_win = NULL;
121
122 static print_args_t  print_args;
123
124 static gboolean print_prefs_init = FALSE;
125
126
127 static void
128 file_print_cmd(gboolean print_selected)
129 {
130   print_args_t *args = &print_args;
131
132   if (print_win != NULL) {
133     /* There's already a "Print" dialog box; reactivate it. */
134     reactivate_window(print_win);
135     return;
136   }
137
138   /* get settings from preferences (and other initial values) only once */
139   if(print_prefs_init == FALSE) {
140       print_prefs_init          = TRUE;
141       args->format              = prefs.pr_format;
142       args->to_file             = prefs.pr_dest;
143       args->file                = g_strdup(prefs.pr_file);
144       args->cmd                 = g_strdup(prefs.pr_cmd);
145       args->print_summary       = TRUE;
146       args->print_dissections   = print_dissections_as_displayed;
147       args->print_hex           = FALSE;
148       args->print_formfeed      = FALSE;
149   }
150
151   /* init the printing range */
152   packet_range_init(&args->range);
153
154   if(print_selected) {
155       args->range.process = range_process_selected;
156   }
157
158   print_win = open_print_dialog("Wireshark: Print", output_action_print, args);
159   SIGNAL_CONNECT(print_win, "destroy", print_destroy_cb, &print_win);
160 }
161
162 void
163 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
164 {
165     file_print_cmd(FALSE);
166 }
167
168 void
169 file_print_selected_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
170 {
171     file_print_cmd(TRUE);
172 }
173
174 /*
175  * Keep a static pointer to the current "Export text" window, if any, so that if
176  * somebody tries to do "File:Export to text" while there's already a "Export text" window
177  * up, we just pop up the existing one, rather than creating a new one.
178  */
179 static GtkWidget *export_text_win = NULL;
180
181 static print_args_t  export_text_args;
182
183 static gboolean export_text_prefs_init = FALSE;
184
185
186 void
187 export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
188 {
189   print_args_t *args = &export_text_args;
190
191 #if _WIN32
192   win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_text);
193   return;
194 #endif
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);
217
218   export_text_win = open_print_dialog("Wireshark: Export as \"Plain Text\" File", output_action_export_text, args);
219   SIGNAL_CONNECT(export_text_win, "destroy", print_destroy_cb, &export_text_win);
220 }
221
222
223 /*
224  * Keep a static pointer to the current "Export ps" window, if any, so that if
225  * somebody tries to do "File:Export to ps" while there's already a "Export ps" window
226  * up, we just pop up the existing one, rather than creating a new one.
227  */
228 static GtkWidget *export_ps_win = NULL;
229
230 static print_args_t  export_ps_args;
231
232 static gboolean export_ps_prefs_init = FALSE;
233
234
235 void
236 export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
237 {
238   print_args_t *args = &export_ps_args;
239
240 #if _WIN32
241   win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_ps);
242   return;
243 #endif
244
245   if (export_ps_win != NULL) {
246     /* There's already a "Export ps" dialog box; reactivate it. */
247     reactivate_window(export_ps_win);
248     return;
249   }
250
251   /* get settings from preferences (and other initial values) only once */
252   if(export_ps_prefs_init == FALSE) {
253       export_ps_prefs_init      = TRUE;
254       args->format              = PR_FMT_PS;
255       args->to_file             = TRUE;
256       args->file                = g_strdup("");
257       args->cmd                 = g_strdup("");
258       args->print_summary       = TRUE;
259       args->print_dissections   = print_dissections_as_displayed;
260       args->print_hex           = FALSE;
261       args->print_formfeed      = FALSE;
262   }
263
264   /* init the printing range */
265   packet_range_init(&args->range);
266
267   export_ps_win = open_print_dialog("Wireshark: Export as \"PostScript\" file", output_action_export_ps, args);
268   SIGNAL_CONNECT(export_ps_win, "destroy", print_destroy_cb, &export_ps_win);
269 }
270
271
272 /*
273  * Keep a static pointer to the current "Export psml" window, if any, so that if
274  * somebody tries to do "File:Export to psml" while there's already a "Export psml" window
275  * up, we just pop up the existing one, rather than creating a new one.
276  */
277 static GtkWidget *export_psml_win = NULL;
278
279 static print_args_t  export_psml_args;
280
281 static gboolean export_psml_prefs_init = FALSE;
282
283
284 void
285 export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
286 {
287   print_args_t *args = &export_psml_args;
288
289 #if _WIN32
290   win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_psml);
291   return;
292 #endif
293
294   if (export_psml_win != NULL) {
295     /* There's already a "Export psml" dialog box; reactivate it. */
296     reactivate_window(export_psml_win);
297     return;
298   }
299
300   /* get settings from preferences (and other initial values) only once */
301   if(export_psml_prefs_init == FALSE) {
302       export_psml_prefs_init    = TRUE;
303       args->format              = PR_FMT_TEXT;  /* XXX */
304       args->to_file             = TRUE;
305       args->file                = g_strdup("");
306       args->cmd                 = g_strdup("");
307       args->print_summary       = TRUE;
308       args->print_dissections   = print_dissections_as_displayed;
309       args->print_hex           = FALSE;
310       args->print_formfeed      = FALSE;
311   }
312
313   /* init the printing range */
314   packet_range_init(&args->range);
315
316   export_psml_win = open_print_dialog("Wireshark: Export as \"PSML\" file", output_action_export_psml, args);
317   SIGNAL_CONNECT(export_psml_win, "destroy", print_destroy_cb, &export_psml_win);
318 }
319
320
321 /*
322  * Keep a static pointer to the current "Export pdml" window, if any, so that if
323  * somebody tries to do "File:Export to pdml" while there's already a "Export pdml" window
324  * up, we just pop up the existing one, rather than creating a new one.
325  */
326 static GtkWidget *export_pdml_win = NULL;
327
328 static print_args_t  export_pdml_args;
329
330 static gboolean export_pdml_prefs_init = FALSE;
331
332
333 void
334 export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
335 {
336   print_args_t *args = &export_pdml_args;
337
338 #if _WIN32
339   win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_pdml);
340   return;
341 #endif
342
343   if (export_pdml_win != NULL) {
344     /* There's already a "Export pdml" dialog box; reactivate it. */
345     reactivate_window(export_pdml_win);
346     return;
347   }
348
349   /* get settings from preferences (and other initial values) only once */
350   if(export_pdml_prefs_init == FALSE) {
351       export_pdml_prefs_init    = TRUE;
352       args->format              = PR_FMT_TEXT;  /* XXX */
353       args->to_file             = TRUE;
354       args->file                = g_strdup("");
355       args->cmd                 = g_strdup("");
356       args->print_summary       = TRUE;
357       args->print_dissections   = print_dissections_as_displayed;
358       args->print_hex           = FALSE;
359       args->print_formfeed      = FALSE;
360   }
361
362   /* init the printing range */
363   packet_range_init(&args->range);
364
365   export_pdml_win = open_print_dialog("Wireshark: Export as \"PDML\" file", output_action_export_pdml, args);
366   SIGNAL_CONNECT(export_pdml_win, "destroy", print_destroy_cb, &export_pdml_win);
367 }
368
369 /*
370  * Keep a static pointer to the current "Export csv" window, if any, so that if
371  * somebody tries to do "File:Export to CSV" while there's already a "Export csv" window
372  * up, we just pop up the existing one, rather than creating a new one.
373  */
374 static GtkWidget *export_csv_win = NULL;
375
376 static print_args_t  export_csv_args;
377
378 static gboolean export_csv_prefs_init = FALSE;
379
380 void
381 export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
382 {
383   print_args_t *args = &export_csv_args;
384
385 #if _WIN32
386   win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_csv);
387   return;
388 #endif
389
390   if (export_csv_win != NULL) {
391     /* There's already a "Export csv" dialog box; reactivate it. */
392     reactivate_window(export_csv_win);
393     return;
394   }
395
396   /* get settings from preferences (and other initial values) only once */
397   if(export_csv_prefs_init == FALSE) {
398       export_csv_prefs_init     = TRUE;
399       args->format              = PR_FMT_TEXT; /* XXX */
400       args->to_file             = TRUE;
401       args->file                = g_strdup("");
402       args->cmd                 = g_strdup("");
403       args->print_summary       = FALSE;
404       args->print_dissections   = print_dissections_none;
405       args->print_hex           = FALSE;
406       args->print_formfeed      = FALSE;
407   }
408
409   /* init the printing range */
410   packet_range_init(&args->range);
411
412   export_csv_win = open_print_dialog("Wireshark: Export as \"Comma Separated Values\" File", output_action_export_csv, args);
413   SIGNAL_CONNECT(export_csv_win, "destroy", print_destroy_cb, &export_csv_win);
414 }
415
416 /*
417  * Keep a static pointer to the current "Export carrays" window, if any, so that if
418  * somebody tries to do "File:Export to carrays" while there's already a "Export carrays" window
419  * up, we just pop up the existing one, rather than creating a new one.
420  */
421 static GtkWidget *export_carrays_win = NULL;
422
423 static print_args_t export_carrays_args;
424
425 static gboolean export_carrays_prefs_init = FALSE;
426
427 void
428 export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
429 {
430   print_args_t *args = &export_carrays_args;
431
432 #if _WIN32
433   win32_export_file(GDK_WINDOW_HWND(top_level->window), export_type_carrays);
434   return;
435 #endif
436
437   if (export_carrays_win != NULL) {
438     /* There's already a "Export carrays" dialog box; reactivate it. */
439     reactivate_window(export_carrays_win);
440     return;
441   }
442
443   /* get settings from preferences (and other initial values) only once */
444   if(export_carrays_prefs_init == FALSE) {
445       export_carrays_prefs_init = TRUE;
446       args->format              = PR_FMT_TEXT;
447       args->to_file             = TRUE;
448       args->file                = g_strdup("");
449       args->cmd                 = g_strdup("");
450       args->print_summary       = FALSE;
451       args->print_dissections   = print_dissections_none;
452       args->print_hex           = FALSE;
453       args->print_formfeed      = FALSE;
454   }
455
456   /* init the printing range */
457   packet_range_init(&args->range);
458
459   export_carrays_win = open_print_dialog("Wireshark: Export as \"C Arrays\" File", 
460                                          output_action_export_carrays, args);
461   SIGNAL_CONNECT(export_carrays_win, "destroy", print_destroy_cb, &export_carrays_win);
462 }
463
464 static void
465 print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
466 {
467     file_selection_browse(file_bt, file_te, "Wireshark: Print to File",
468                           FILE_SELECTION_WRITE_BROWSE);
469 }
470
471
472
473 /* Open the print dialog */
474 static GtkWidget *
475 open_print_dialog(const char *title, output_action_e action, print_args_t *args)
476 {
477   GtkWidget     *main_win;
478   GtkWidget     *main_vb;
479
480   GtkWidget     *printer_fr, *printer_vb, *export_format_lb;
481   GtkWidget     *text_rb, *ps_rb, *pdml_rb, *psml_rb, *csv_rb, *carrays_rb;
482   GtkWidget     *printer_tb, *dest_cb;
483 #ifndef _WIN32
484   GtkWidget     *cmd_lb, *cmd_te;
485 #endif
486   GtkWidget     *file_bt, *file_te;
487
488   GtkWidget     *range_fr, *range_tb;
489
490   GtkWidget     *packet_hb;
491
492   GtkWidget     *format_fr, *format_vb;
493   GtkWidget     *summary_cb;
494
495   GtkWidget     *details_cb;
496   GtkWidget     *details_hb, *details_vb;
497   GtkWidget     *collapse_all_rb, *as_displayed_rb, *expand_all_rb;
498   GtkWidget     *hex_cb;
499   GtkWidget     *sep, *formfeed_cb;
500
501   GtkWidget     *bbox, *ok_bt, *cancel_bt, *help_bt;
502
503   GtkTooltips   *tooltips;
504
505
506   /* dialog window */
507   main_win = dlg_window_new(title);
508
509   /* Enable tooltips */
510   tooltips = gtk_tooltips_new();
511
512   /* Vertical enclosing container for each row of widgets */
513   main_vb = gtk_vbox_new(FALSE, 5);
514   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
515   gtk_container_add(GTK_CONTAINER(main_win), main_vb);
516   gtk_widget_show(main_vb);
517
518 /*****************************************************/
519
520   /*** printer frame ***/
521   printer_fr = gtk_frame_new(action == output_action_print ? "Printer" : "Export to file:");
522   gtk_box_pack_start(GTK_BOX(main_vb), printer_fr, FALSE, FALSE, 0);
523   gtk_widget_show(printer_fr);
524   printer_vb = gtk_vbox_new(FALSE, 5);
525   gtk_container_border_width(GTK_CONTAINER(printer_vb), 5);
526   gtk_container_add(GTK_CONTAINER(printer_fr), printer_vb);
527   gtk_widget_show(printer_vb);
528
529   /* "Plain text" / "Postscript" / "PDML", ... radio buttons */
530   text_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "Plain _text", accel_group);
531   if (args->format == PR_FMT_TEXT)
532     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(text_rb), TRUE);
533   gtk_tooltips_set_tip (tooltips, text_rb, "Print output in ascii \"plain text\" format. If you're unsure, use this format.", NULL);
534   gtk_box_pack_start(GTK_BOX(printer_vb), text_rb, FALSE, FALSE, 0);
535   if(action == output_action_print)
536     gtk_widget_show(text_rb);
537
538   ps_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "_PostScript", accel_group);
539   if (args->format == PR_FMT_PS)
540     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ps_rb), TRUE);
541   gtk_tooltips_set_tip (tooltips, ps_rb, "Print output in \"postscript\" format, for postscript capable printers or print servers.", NULL);
542   gtk_box_pack_start(GTK_BOX(printer_vb), ps_rb, FALSE, FALSE, 0);
543   if(action == output_action_print)
544     gtk_widget_show(ps_rb);
545
546   pdml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PDM_L (XML: Packet Details Markup Language)", accel_group);
547   if (action == output_action_export_pdml)
548     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(pdml_rb), TRUE);
549   gtk_tooltips_set_tip (tooltips, pdml_rb,
550       "Print output in \"PDML\" (Packet Details Markup Language), "
551       "an XML based packet data interchange format. "
552       "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.", NULL);
553   gtk_box_pack_start(GTK_BOX(printer_vb), pdml_rb, FALSE, FALSE, 0);
554   /* gtk_widget_show(pdml_rb); */
555
556   psml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PSML (XML: Packet Summary Markup Language)", accel_group);
557   if (action == output_action_export_psml)
558     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(psml_rb), TRUE);
559   gtk_tooltips_set_tip (tooltips, psml_rb,
560       "Print output in \"PSML\" (Packet Summary Markup Language), "
561       "an XML based packet summary interchange format. "
562       "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.", NULL);
563   gtk_box_pack_start(GTK_BOX(printer_vb), psml_rb, FALSE, FALSE, 0);
564   /* gtk_widget_show(psml_rb); */
565
566   csv_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "_CSV", accel_group);
567   if (action == output_action_export_csv)
568     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(csv_rb), TRUE);
569   gtk_tooltips_set_tip (tooltips, csv_rb,
570       "Print output in \"Comma Separated Values\" (CSV) format, "
571       "a text format compatible with OpenOffice and Excel. "
572       "One row for each packet, with its timestamp and size.", NULL);
573   gtk_box_pack_start(GTK_BOX(printer_vb), csv_rb, FALSE, FALSE, 0);
574   /* gtk_widget_show(csv_rb); */
575
576   carrays_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "C Arrays", accel_group);
577   if (action == output_action_export_carrays)
578     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(carrays_rb), TRUE);
579   gtk_tooltips_set_tip (tooltips, carrays_rb,
580       "Print output in C Arrays format, "
581       "a text file suitable for use in C/C++ programs. "
582       "One char[] for each packet.", NULL);
583   gtk_box_pack_start(GTK_BOX(printer_vb), carrays_rb, FALSE, FALSE, 0);
584   /* gtk_widget_show(carrays_rb); */
585
586   /* printer table */
587 #ifndef _WIN32
588   printer_tb = gtk_table_new(2, 3, FALSE);
589 #else
590   printer_tb = gtk_table_new(2, 2, FALSE);
591 #endif
592   gtk_box_pack_start(GTK_BOX(printer_vb), printer_tb, FALSE, FALSE, 0);
593   gtk_table_set_row_spacings(GTK_TABLE(printer_tb), 5);
594   gtk_table_set_col_spacings(GTK_TABLE(printer_tb), 5);
595   gtk_widget_show(printer_tb);
596
597
598   /* Output to file button */
599   dest_cb = gtk_check_button_new_with_mnemonic("Output to _file:");
600   if (args->to_file)
601     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
602   gtk_tooltips_set_tip (tooltips, dest_cb, "Output to file instead of printer", NULL);
603   gtk_table_attach_defaults(GTK_TABLE(printer_tb), dest_cb, 0, 1, 0, 1);
604   if(action == output_action_print)
605     gtk_widget_show(dest_cb);
606
607   /* File text entry */
608   file_te = gtk_entry_new();
609   g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_TE_KEY, file_te);
610   gtk_tooltips_set_tip (tooltips, file_te, "Enter Output filename", NULL);
611   gtk_entry_set_text(GTK_ENTRY(file_te), args->file);
612   gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_te, 1, 2, 0, 1);
613   gtk_widget_set_sensitive(file_te, args->to_file);
614   gtk_widget_show(file_te);
615   if (args->to_file)
616     gtk_widget_grab_focus(file_te);
617
618   /* "Browse" button */
619   file_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
620   g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_BT_KEY, file_bt);
621   g_object_set_data(G_OBJECT(file_bt), PRINT_TE_PTR_KEY, file_te);
622   gtk_tooltips_set_tip (tooltips, file_bt, "Browse output filename in filesystem", NULL);
623   gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_bt, 2, 3, 0, 1);
624   gtk_widget_set_sensitive(file_bt, args->to_file);
625   gtk_widget_show(file_bt);
626
627   /* Command label and text entry */
628 #ifndef _WIN32
629   cmd_lb = gtk_label_new("Print command:");
630   g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_LB_KEY, cmd_lb);
631   gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
632   gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_lb, 0, 1, 1, 2);
633   gtk_widget_set_sensitive(cmd_lb, !args->to_file);
634   if(action == output_action_print)
635     gtk_widget_show(cmd_lb);
636
637   cmd_te = gtk_entry_new();
638   g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_TE_KEY, cmd_te);
639   gtk_tooltips_set_tip (tooltips, cmd_te, "Enter print command", NULL);
640   gtk_entry_set_text(GTK_ENTRY(cmd_te), args->cmd);
641   gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_te, 1, 2, 1, 2);
642   gtk_widget_set_sensitive(cmd_te, !args->to_file);
643   if(action == output_action_print)
644     gtk_widget_show(cmd_te);
645 #endif
646
647   SIGNAL_CONNECT(dest_cb, "toggled", print_cmd_toggle_dest, NULL);
648   SIGNAL_CONNECT(file_bt, "clicked", print_browse_file_cb, file_te);
649
650   if(action == output_action_export_ps) {
651     export_format_lb = gtk_label_new("(PostScript files can be easily converted to PDF files using ghostscript's ps2pdf)");
652     gtk_box_pack_start(GTK_BOX(printer_vb), export_format_lb, FALSE, FALSE, 0);
653     gtk_widget_show(export_format_lb);
654   }
655
656 /*****************************************************/
657
658   /*** hor box for range and format frames ***/
659   packet_hb = gtk_hbox_new(FALSE, 5);
660   gtk_container_add(GTK_CONTAINER(main_vb), packet_hb);
661   gtk_widget_show(packet_hb);
662
663   /*** packet range frame ***/
664   range_fr = gtk_frame_new("Packet Range");
665   gtk_box_pack_start(GTK_BOX(packet_hb), range_fr, FALSE, FALSE, 0);
666   gtk_widget_show(range_fr);
667
668   range_tb = range_new(&args->range);
669   gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
670   gtk_widget_show(range_tb);
671
672 /*****************************************************/
673
674   /*** packet format frame ***/
675   format_fr = gtk_frame_new("Packet Format");
676   gtk_box_pack_start(GTK_BOX(packet_hb), format_fr, TRUE, TRUE, 0);
677   if(   action == output_action_print ||
678         action == output_action_export_text ||
679         action == output_action_export_ps)
680     gtk_widget_show(format_fr);
681   format_vb = gtk_vbox_new(FALSE, 5);
682   gtk_container_border_width(GTK_CONTAINER(format_vb), 5);
683   gtk_container_add(GTK_CONTAINER(format_fr), format_vb);
684   gtk_widget_show(format_vb);
685
686   /* "Print summary line" check button */
687   summary_cb = gtk_check_button_new_with_mnemonic("Packet summary line");
688   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(summary_cb), args->print_summary);
689   SIGNAL_CONNECT(summary_cb, "clicked", print_cmd_toggle_detail, main_win);
690   gtk_tooltips_set_tip (tooltips, summary_cb, "Output of a packet summary line, like in the packet list", NULL);
691   gtk_container_add(GTK_CONTAINER(format_vb), summary_cb);
692   gtk_widget_show(summary_cb);
693
694
695   /* "Details" check button */
696   details_cb = gtk_check_button_new_with_mnemonic("Packet details:");
697   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(details_cb), args->print_dissections != print_dissections_none);
698   SIGNAL_CONNECT(details_cb, "clicked", print_cmd_toggle_detail, main_win);
699   gtk_tooltips_set_tip (tooltips, details_cb, "Output format of the selected packet details (protocol tree).", NULL);
700   gtk_container_add(GTK_CONTAINER(format_vb), details_cb);
701   gtk_widget_show(details_cb);
702
703   /*** packet details ***/
704   details_hb = gtk_hbox_new(FALSE, 6);
705   gtk_container_border_width(GTK_CONTAINER(details_hb), 0);
706   gtk_container_add(GTK_CONTAINER(format_vb), details_hb);
707   gtk_widget_show(details_hb);
708
709   details_vb = gtk_vbox_new(FALSE, 6);
710   gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
711   gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
712   gtk_widget_show(details_vb);
713
714   details_vb = gtk_vbox_new(FALSE, 6);
715   gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
716   gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
717   gtk_widget_show(details_vb);
718
719   /* "All collapsed"/"As displayed"/"All Expanded" radio buttons */
720   collapse_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "All co_llapsed", accel_group);
721   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(collapse_all_rb), args->print_dissections == print_dissections_collapsed);
722   gtk_tooltips_set_tip (tooltips, collapse_all_rb, "Output of the packet details tree \"collapsed\"", NULL);
723   gtk_container_add(GTK_CONTAINER(details_vb), collapse_all_rb);
724   gtk_widget_show(collapse_all_rb);
725
726   as_displayed_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "As displa_yed", accel_group);
727   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(as_displayed_rb), args->print_dissections == print_dissections_as_displayed);
728   gtk_tooltips_set_tip (tooltips, as_displayed_rb, "Output of the packet details tree \"as displayed\"", NULL);
729   gtk_container_add(GTK_CONTAINER(details_vb), as_displayed_rb);
730   gtk_widget_show(as_displayed_rb);
731
732   expand_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "All e_xpanded", accel_group);
733   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(expand_all_rb), args->print_dissections == print_dissections_expanded);
734   gtk_tooltips_set_tip (tooltips, expand_all_rb, "Output of the packet details tree \"expanded\"", NULL);
735   gtk_container_add(GTK_CONTAINER(details_vb), expand_all_rb);
736   gtk_widget_show(expand_all_rb);
737
738   /* "Print hex" check button. */
739   hex_cb = gtk_check_button_new_with_mnemonic("Packet bytes");
740   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_cb), args->print_hex);
741   SIGNAL_CONNECT(hex_cb, "clicked", print_cmd_toggle_detail, main_win);
742   gtk_tooltips_set_tip (tooltips, hex_cb, "Add a hexdump of the packet data", NULL);
743   gtk_container_add(GTK_CONTAINER(format_vb), hex_cb);
744   gtk_widget_show(hex_cb);
745
746   /* seperator */
747   sep = gtk_hseparator_new();
748   gtk_container_add(GTK_CONTAINER(format_vb), sep);
749   gtk_widget_show(sep);
750
751   /* "Each packet on a new page" check button. */
752   formfeed_cb = gtk_check_button_new_with_mnemonic("Each packet on a new page");
753   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(formfeed_cb), args->print_formfeed);
754   gtk_tooltips_set_tip (tooltips, formfeed_cb, "When checked, a new page will be used for each packet. "
755       "This is done by adding a formfeed (or similar) between the packet outputs.", NULL);
756   gtk_container_add(GTK_CONTAINER(format_vb), formfeed_cb);
757   gtk_widget_show(formfeed_cb);
758
759
760   g_object_set_data(G_OBJECT(main_win), PRINT_ARGS_KEY, args);
761   g_object_set_data(G_OBJECT(main_win), PRINT_SUMMARY_CB_KEY, summary_cb);
762   g_object_set_data(G_OBJECT(main_win), PRINT_DETAILS_CB_KEY, details_cb);
763   g_object_set_data(G_OBJECT(main_win), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
764   g_object_set_data(G_OBJECT(main_win), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
765   g_object_set_data(G_OBJECT(main_win), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
766   g_object_set_data(G_OBJECT(main_win), PRINT_HEX_CB_KEY, hex_cb);
767
768 /*****************************************************/
769
770
771   /* Button row */
772   if(topic_available(HELP_PRINT_DIALOG)) {
773     bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
774   } else {
775     bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL);
776   }
777   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
778   gtk_widget_show(bbox);
779
780   ok_bt = g_object_get_data(G_OBJECT(bbox), action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK);
781
782   g_object_set_data(G_OBJECT(main_win), PRINT_BT_KEY, ok_bt);
783
784   g_object_set_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY, ps_rb);
785   g_object_set_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY, pdml_rb);
786   g_object_set_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY, psml_rb);
787   g_object_set_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY, csv_rb);
788   g_object_set_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY, carrays_rb);
789   g_object_set_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY, dest_cb);
790 #ifndef _WIN32
791   g_object_set_data(G_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
792 #endif
793
794   g_object_set_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY, args);
795   g_object_set_data(G_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
796   g_object_set_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY, summary_cb);
797   g_object_set_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY, details_cb);
798   g_object_set_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
799   g_object_set_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
800   g_object_set_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
801   g_object_set_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY, hex_cb);
802   g_object_set_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY, formfeed_cb);
803   SIGNAL_CONNECT(ok_bt, "clicked", print_ok_cb, main_win);
804   gtk_tooltips_set_tip (tooltips, ok_bt, "Start output", NULL);
805
806   cancel_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
807   window_set_cancel_button(main_win, cancel_bt, window_cancel_button_cb);
808   gtk_tooltips_set_tip (tooltips, cancel_bt, "Cancel and exit dialog", NULL);
809
810   if(action == output_action_print) {
811     if(topic_available(HELP_PRINT_DIALOG)) {
812         help_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
813       SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_PRINT_DIALOG);
814     }
815   } else {
816 #if _WIN32
817     if(topic_available(HELP_EXPORT_FILE_WIN32_DIALOG)) {
818         help_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
819       SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_EXPORT_FILE_WIN32_DIALOG);
820     }
821 #else
822     if(topic_available(HELP_EXPORT_FILE_DIALOG)) {
823         help_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
824       SIGNAL_CONNECT(help_bt, "clicked", topic_cb, HELP_EXPORT_FILE_DIALOG);
825     }
826 #endif
827   }
828
829   gtk_widget_grab_default(ok_bt);
830
831   /* Catch the "activate" signal on the "Command" and "File" text entries,
832      so that if the user types Return there, we act as if the "OK" button
833      had been selected, as happens if Return is typed if some widget
834      that *doesn't* handle the Return key has the input focus. */
835 #ifndef _WIN32
836   dlg_set_activate(cmd_te, ok_bt);
837 #endif
838   if(action != output_action_print)
839     dlg_set_activate(file_te, ok_bt);
840
841   SIGNAL_CONNECT(main_win, "delete_event", window_delete_event_cb, NULL);
842
843   gtk_widget_show(main_win);
844   window_present(main_win);
845
846   return main_win;
847 }
848
849
850 /* user changed "print to" destination */
851 static void
852 print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
853 {
854 #ifndef _WIN32
855   GtkWidget     *cmd_lb, *cmd_te;
856 #endif
857   GtkWidget     *file_bt, *file_te;
858   int            to_file;
859
860 #ifndef _WIN32
861   cmd_lb = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_LB_KEY));
862   cmd_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_TE_KEY));
863 #endif
864   file_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_BT_KEY));
865   file_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_TE_KEY));
866
867   to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
868 #ifndef _WIN32
869   gtk_widget_set_sensitive(cmd_lb, !to_file);
870   gtk_widget_set_sensitive(cmd_te, !to_file);
871 #endif
872   gtk_widget_set_sensitive(file_bt, to_file);
873   gtk_widget_set_sensitive(file_te, to_file);
874 }
875
876
877 /* user changed "packet details" */
878 static void
879 print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
880 {
881   GtkWidget     *print_bt, *summary_cb, *details_cb, *collapse_all_rb, *expand_all_rb, *as_displayed_rb, *hex_cb;
882   gboolean      print_detail;
883
884
885   print_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_BT_KEY));
886   summary_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_SUMMARY_CB_KEY));
887   details_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_DETAILS_CB_KEY));
888   collapse_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_COLLAPSE_ALL_RB_KEY));
889   as_displayed_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_AS_DISPLAYED_RB_KEY));
890   expand_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_EXPAND_ALL_RB_KEY));
891   hex_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_HEX_CB_KEY));
892
893   /* is user disabled details, disable the corresponding buttons */
894   print_detail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb));
895   gtk_widget_set_sensitive(collapse_all_rb, print_detail);
896   gtk_widget_set_sensitive(as_displayed_rb, print_detail);
897   gtk_widget_set_sensitive(expand_all_rb, print_detail);
898
899   /* if user selected nothing to print at all, disable the "ok" button */
900   gtk_widget_set_sensitive(print_bt,
901       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (summary_cb)) ||
902       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb)) ||
903       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_cb)));
904 }
905
906
907 static void
908 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
909 {
910   GtkWidget         *button;
911   print_args_t      *args;
912   const gchar       *g_dest;
913   gchar             *f_name;
914   gchar             *dirname;
915   gboolean          export_as_pdml = FALSE, export_as_psml = FALSE;
916   gboolean          export_as_csv = FALSE;
917   gboolean          export_as_carrays = FALSE;
918 #ifdef _WIN32
919   gboolean          win_printer = FALSE;
920   int               tmp_fd;
921   char              tmp_namebuf[128+1];    /* XXX - length was used elsewhere too, why? */
922   char              *tmp_oldfile;
923 #endif
924   cf_print_status_t status;
925
926   args = (print_args_t *)g_object_get_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY);
927
928   /* Check whether the range is valid. */
929   if (!range_check_validity(&args->range)) {
930     /* The range isn't valid; don't dismiss the print/export dialog box,
931        just leave it around so that the user can, after they
932        dismiss the alert box popped up for the error, try again. */
933     return;
934   }
935
936   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY);
937   args->to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
938
939   if (args->to_file) {
940       g_dest = gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
941                                                           PRINT_FILE_TE_KEY)));
942     if (!g_dest[0]) {
943       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
944         "Output to file, but no file specified.");
945       return;
946     }
947     g_free(args->file);
948     args->file = g_strdup(g_dest);
949     /* Save the directory name for future file dialogs. */
950     f_name = g_strdup(g_dest);
951     dirname = get_dirname(f_name);  /* Overwrites f_name */
952     set_last_open_dir(dirname);
953     g_free(f_name);
954   } else {
955 #ifdef _WIN32
956     win_printer = TRUE;
957     /* We currently don't have a function in util.h to create just a tempfile */
958     /* name, so simply create a tempfile using the "official" function, */
959     /* then delete this file again. After this, the name MUST be available. */
960     /* */
961     /* Don't use tmpnam() or such, as this will fail under some ACL */
962     /* circumstances: http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=358 */
963
964     tmp_fd = create_tempfile(tmp_namebuf, sizeof(tmp_namebuf), "ethprint");
965     if(tmp_fd == -1) {
966         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
967             "Couldn't create a temporary file for printing.");
968         return;
969     }
970     /* remember to restore these values later! */
971     tmp_oldfile = args->file;
972     args->file = g_strdup(tmp_namebuf);
973     eth_unlink(args->file);
974     args->to_file = TRUE;
975 #else
976     g_free(args->cmd);
977     args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
978       PRINT_CMD_TE_KEY))));
979 #endif
980   }
981
982   args->format = PR_FMT_TEXT;
983   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY);
984   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
985     args->format = PR_FMT_PS;
986   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY);
987   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
988     export_as_pdml = TRUE;
989   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY);
990   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
991     export_as_psml = TRUE;
992   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY);
993   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
994     export_as_csv = TRUE;
995   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY);
996   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
997     export_as_carrays = TRUE;
998
999   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY);
1000   args->print_summary = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1001
1002   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY);
1003   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1004     args->print_dissections = print_dissections_collapsed;
1005   }
1006   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY);
1007   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1008     args->print_dissections = print_dissections_as_displayed;
1009   }
1010   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY);
1011   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1012     args->print_dissections = print_dissections_expanded;
1013   }
1014
1015   /* the details setting has priority over the radio buttons */
1016   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY);
1017   if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
1018     args->print_dissections = print_dissections_none;
1019   }
1020
1021   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY);
1022   args->print_hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1023
1024   button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY);
1025   args->print_formfeed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
1026
1027
1028   window_destroy(GTK_WIDGET(parent_w));
1029
1030   /* Now print/export the packets */
1031   if (export_as_pdml)
1032     status = cf_write_pdml_packets(&cfile, args);
1033   else if (export_as_psml)
1034     status = cf_write_psml_packets(&cfile, args);
1035   else if (export_as_csv)
1036     status = cf_write_csv_packets(&cfile, args);
1037   else if (export_as_carrays)
1038     status = cf_write_carrays_packets(&cfile, args);
1039   else {
1040     switch (args->format) {
1041
1042     case PR_FMT_TEXT:
1043       if (args->to_file) {
1044         args->stream = print_stream_text_new(TRUE, args->file);
1045         if (args->stream == NULL) {
1046           open_failure_alert_box(args->file, errno, TRUE);
1047           return;
1048         }
1049       } else {
1050         args->stream = print_stream_text_new(FALSE, args->cmd);
1051         if (args->stream == NULL) {
1052           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1053                         "Couldn't run print command %s.", args->cmd);
1054         }
1055       }
1056       break;
1057
1058     case PR_FMT_PS:
1059       if (args->to_file) {
1060         args->stream = print_stream_ps_new(TRUE, args->file);
1061         if (args->stream == NULL) {
1062           open_failure_alert_box(args->file, errno, TRUE);
1063           return;
1064         }
1065       } else {
1066         args->stream = print_stream_ps_new(FALSE, args->cmd);
1067         if (args->stream == NULL) {
1068           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1069                         "Couldn't run print command %s.", args->cmd);
1070         }
1071       }
1072       break;
1073
1074     default:
1075       g_assert_not_reached();
1076       return;
1077     }
1078     status = cf_print_packets(&cfile, args);
1079   }
1080   switch (status) {
1081
1082   case CF_PRINT_OK:
1083     break;
1084
1085   case CF_PRINT_OPEN_ERROR:
1086     if (args->to_file)
1087       open_failure_alert_box(args->file, errno, TRUE);
1088     else
1089       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't run print command %s.",
1090         args->cmd);
1091     break;
1092
1093   case CF_PRINT_WRITE_ERROR:
1094     if (args->to_file)
1095       write_failure_alert_box(args->file, errno);
1096     else
1097       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
1098         "Error writing to print command: %s", strerror(errno));
1099     break;
1100   }
1101
1102 #ifdef _WIN32
1103   if (win_printer) {
1104     print_mswin(args->file);
1105
1106     /* trash temp file */
1107     eth_remove(args->file);
1108
1109     /* restore old settings */
1110     args->to_file = FALSE;
1111     args->file = tmp_oldfile;
1112   }
1113 #endif
1114 }
1115
1116 static void
1117 print_destroy_cb(GtkWidget *win, gpointer user_data)
1118 {
1119   GtkWidget     *fs;
1120
1121   /* Is there a file selection dialog associated with this
1122      Print File dialog? */
1123   fs = g_object_get_data(G_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
1124
1125   if (fs != NULL) {
1126     /* Yes.  Destroy it. */
1127     window_destroy(fs);
1128   }
1129
1130   /* Note that we no longer have a "Print" dialog box. */
1131   *((gpointer *) user_data) = NULL;
1132 }