Fix the wireless settings button for AirPCap devices in the
[obnox/wireshark/wip.git] / gtk / print_dlg.c
index 9ffa1356416274e7a1deb5daaa045b15d490cadd..6f95902dbc09beb4da9fae414036a402bd17d047 100644 (file)
@@ -1,10 +1,10 @@
 /* print_dlg.c
- * Dialog boxes for printing
+ * Dialog boxes for printing and exporting to text files
  *
- * $Id: print_dlg.c,v 1.73 2004/04/25 12:04:08 ulfl Exp $
+ * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
 
 #include <gtk/gtk.h>
 
-#include "globals.h"
-#include "keys.h"
-#include "print.h"
-#include "prefs.h"
-#include "alert_box.h"
-#include "simple_dialog.h"
-#include "file_dlg.h"
-#include "ui_util.h"
-#include "dlg_utils.h"
-#include "main.h"
+#include <epan/prefs.h>
 #include <epan/epan_dissect.h>
 #include <epan/filesystem.h>
+
+#include "../print.h"
+#include "../alert_box.h"
+#include "../simple_dialog.h"
+#include "../util.h"
+#include <wsutil/file_util.h>
+
+#include "gtk/gtkglobals.h"
+#include "gtk/keys.h"
+#include "gtk/capture_file_dlg.h"
+#include "gtk/gui_utils.h"
+#include "gtk/dlg_utils.h"
+#include "gtk/file_dlg.h"
+#include "gtk/main.h"
+#include "gtk/stock_icons.h"
+#include "gtk/range_utils.h"
+#include "gtk/help_dlg.h"
+
 #ifdef _WIN32
-#include <io.h>
-#include "print_mswin.h"
+#include <gdk/gdkwin32.h>
+#include <windows.h>
+#include "win32/file_dlg_win32.h"
+#include "win32/print_win32.h"
+#include "../tempfile.h"
 #endif
-#include "compat_macros.h"
-#include "range_utils.h"
+
+/* dialog output action */
+typedef enum {
+  output_action_print,          /* print text to printer */
+  output_action_export_text,    /* export to plain text */
+  output_action_export_ps,      /* export to postscript */
+  output_action_export_psml,    /* export to packet summary markup language */
+  output_action_export_pdml,    /* export to packet data markup language */
+  output_action_export_csv,     /* export to csv file */
+  output_action_export_carrays  /* export to C array file */
+} output_action_e;
 
 
 /* On Win32, a GUI application apparently can't use "popen()" (it
   for this (and also use various UNIX printing APIs, when present?).
 */
 
+static GtkWidget *
+open_print_dialog(const char *title, output_action_e action, print_args_t *args);
 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
-static void print_close_cb(GtkWidget *close_bt, gpointer parent_w);
 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
 
 
@@ -72,6 +94,8 @@ static void print_destroy_cb(GtkWidget *win, gpointer user_data);
 #define PRINT_PS_RB_KEY           "printer_ps_radio_button"
 #define PRINT_PDML_RB_KEY         "printer_pdml_radio_button"
 #define PRINT_PSML_RB_KEY         "printer_psml_radio_button"
+#define PRINT_CSV_RB_KEY          "printer_csv_radio_button"
+#define PRINT_CARRAYS_RB_KEY      "printer_carrays_radio_button"
 #define PRINT_DEST_CB_KEY         "printer_destination_check_button"
 
 #define PRINT_SUMMARY_CB_KEY      "printer_summary_check_button"
@@ -84,30 +108,399 @@ static void print_destroy_cb(GtkWidget *win, gpointer user_data);
 
 #define PRINT_BT_KEY              "printer_button"
 
+#define PRINT_TE_PTR_KEY          "printer_file_te_ptr"
+
+
 /*
  * Keep a static pointer to the current "Print" window, if any, so that if
  * somebody tries to do "File:Print" while there's already a "Print" window
  * up, we just pop up the existing one, rather than creating a new one.
  */
-static GtkWidget *print_w = NULL;
+static GtkWidget *print_win = NULL;
 
 static print_args_t  print_args;
 
 static gboolean print_prefs_init = FALSE;
 
 
-/* Open the print dialog */
+static void
+file_print_cmd(gboolean print_selected)
+{
+  print_args_t *args = &print_args;
+
+  if (print_win != NULL) {
+    /* There's already a "Print" dialog box; reactivate it. */
+    reactivate_window(print_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(print_prefs_init == FALSE) {
+      print_prefs_init          = TRUE;
+      args->format              = prefs.pr_format;
+      args->to_file             = prefs.pr_dest;
+      args->file                = g_strdup(prefs.pr_file);
+      args->cmd                 = g_strdup(prefs.pr_cmd);
+      args->print_summary       = TRUE;
+      args->print_dissections   = print_dissections_as_displayed;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  if(print_selected) {
+      args->range.process = range_process_selected;
+  }
+
+  print_win = open_print_dialog("Wireshark: Print", output_action_print, args);
+  g_signal_connect(print_win, "destroy", G_CALLBACK(print_destroy_cb), &print_win);
+}
+
 void
 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
 {
-#if GTK_MAJOR_VERSION < 2
-  GtkAccelGroup *accel_group;
+    file_print_cmd(FALSE);
+}
+
+void
+file_print_selected_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+    file_print_cmd(TRUE);
+}
+
+/*
+ * Keep a static pointer to the current "Export text" window, if any, so that if
+ * somebody tries to do "File:Export to text" while there's already a "Export text" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_text_win = NULL;
+
+static print_args_t  export_text_args;
+
+static gboolean export_text_prefs_init = FALSE;
+
+
+#ifdef _WIN32
+void
+export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), export_type_text);
+  return;
+}
+#else
+void
+export_text_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_text_args;
+
+  if (export_text_win != NULL) {
+    /* There's already a "Export text" dialog box; reactivate it. */
+    reactivate_window(export_text_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_text_prefs_init == FALSE) {
+      export_text_prefs_init    = TRUE;
+      args->format              = PR_FMT_TEXT;
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = TRUE;
+      args->print_dissections   = print_dissections_as_displayed;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_text_win = open_print_dialog("Wireshark: Export as \"Plain Text\" File", output_action_export_text, args);
+  g_signal_connect(export_text_win, "destroy", G_CALLBACK(print_destroy_cb), &export_text_win);
+}
+#endif
+
+
+/*
+ * Keep a static pointer to the current "Export ps" window, if any, so that if
+ * somebody tries to do "File:Export to ps" while there's already a "Export ps" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_ps_win = NULL;
+
+static print_args_t  export_ps_args;
+
+static gboolean export_ps_prefs_init = FALSE;
+
+
+#ifdef _WIN32
+void
+export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), export_type_ps);
+  return;
+}
+#else
+void
+export_ps_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_ps_args;
+
+  if (export_ps_win != NULL) {
+    /* There's already a "Export ps" dialog box; reactivate it. */
+    reactivate_window(export_ps_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_ps_prefs_init == FALSE) {
+      export_ps_prefs_init      = TRUE;
+      args->format              = PR_FMT_PS;
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = TRUE;
+      args->print_dissections   = print_dissections_as_displayed;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_ps_win = open_print_dialog("Wireshark: Export as \"PostScript\" file", output_action_export_ps, args);
+  g_signal_connect(export_ps_win, "destroy", G_CALLBACK(print_destroy_cb), &export_ps_win);
+}
 #endif
 
+
+/*
+ * Keep a static pointer to the current "Export psml" window, if any, so that if
+ * somebody tries to do "File:Export to psml" while there's already a "Export psml" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_psml_win = NULL;
+
+static print_args_t  export_psml_args;
+
+static gboolean export_psml_prefs_init = FALSE;
+
+
+#ifdef _WIN32
+void
+export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), export_type_psml);
+  return;
+}
+#else
+void
+export_psml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_psml_args;
+
+  if (export_psml_win != NULL) {
+    /* There's already a "Export psml" dialog box; reactivate it. */
+    reactivate_window(export_psml_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_psml_prefs_init == FALSE) {
+      export_psml_prefs_init    = TRUE;
+      args->format              = PR_FMT_TEXT; /* XXX */
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = TRUE;
+      args->print_dissections   = print_dissections_as_displayed;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_psml_win = open_print_dialog("Wireshark: Export as \"PSML\" file", output_action_export_psml, args);
+  g_signal_connect(export_psml_win, "destroy", G_CALLBACK(print_destroy_cb), &export_psml_win);
+}
+#endif
+
+/*
+ * Keep a static pointer to the current "Export pdml" window, if any, so that if
+ * somebody tries to do "File:Export to pdml" while there's already a "Export pdml" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_pdml_win = NULL;
+
+static print_args_t  export_pdml_args;
+
+static gboolean export_pdml_prefs_init = FALSE;
+
+
+#ifdef _WIN32
+void
+export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), export_type_pdml);
+  return;
+}
+#else
+void
+export_pdml_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_pdml_args;
+
+  if (export_pdml_win != NULL) {
+    /* There's already a "Export pdml" dialog box; reactivate it. */
+    reactivate_window(export_pdml_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_pdml_prefs_init == FALSE) {
+      export_pdml_prefs_init    = TRUE;
+      args->format              = PR_FMT_TEXT; /* XXX */
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = TRUE;
+      args->print_dissections   = print_dissections_as_displayed;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_pdml_win = open_print_dialog("Wireshark: Export as \"PDML\" file", output_action_export_pdml, args);
+  g_signal_connect(export_pdml_win, "destroy", G_CALLBACK(print_destroy_cb), &export_pdml_win);
+}
+#endif
+
+/*
+ * Keep a static pointer to the current "Export csv" window, if any, so that if
+ * somebody tries to do "File:Export to CSV" while there's already a "Export csv" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_csv_win = NULL;
+
+static print_args_t  export_csv_args;
+
+static gboolean export_csv_prefs_init = FALSE;
+
+#ifdef _WIN32
+void
+export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), export_type_csv);
+  return;
+}
+#else
+void
+export_csv_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_csv_args;
+
+  if (export_csv_win != NULL) {
+    /* There's already a "Export csv" dialog box; reactivate it. */
+    reactivate_window(export_csv_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_csv_prefs_init == FALSE) {
+      export_csv_prefs_init     = TRUE;
+      args->format              = PR_FMT_TEXT; /* XXX */
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = FALSE;
+      args->print_dissections   = print_dissections_none;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_csv_win = open_print_dialog("Wireshark: Export as \"Comma Separated Values\" File", output_action_export_csv, args);
+  g_signal_connect(export_csv_win, "destroy", G_CALLBACK(print_destroy_cb), &export_csv_win);
+}
+#endif
+
+/*
+ * Keep a static pointer to the current "Export carrays" window, if any, so that if
+ * somebody tries to do "File:Export to carrays" while there's already a "Export carrays" window
+ * up, we just pop up the existing one, rather than creating a new one.
+ */
+static GtkWidget *export_carrays_win = NULL;
+
+static print_args_t export_carrays_args;
+
+static gboolean export_carrays_prefs_init = FALSE;
+
+#ifdef _WIN32
+void
+export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  win32_export_file(GDK_WINDOW_HWND(gtk_widget_get_window(top_level)), export_type_carrays);
+  return;
+}
+#else
+void
+export_carrays_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
+{
+  print_args_t *args = &export_carrays_args;
+
+  if (export_carrays_win != NULL) {
+    /* There's already a "Export carrays" dialog box; reactivate it. */
+    reactivate_window(export_carrays_win);
+    return;
+  }
+
+  /* get settings from preferences (and other initial values) only once */
+  if(export_carrays_prefs_init == FALSE) {
+      export_carrays_prefs_init = TRUE;
+      args->format              = PR_FMT_TEXT;
+      args->to_file             = TRUE;
+      args->file                = g_strdup("");
+      args->cmd                 = g_strdup("");
+      args->print_summary       = FALSE;
+      args->print_dissections   = print_dissections_none;
+      args->print_hex           = FALSE;
+      args->print_formfeed      = FALSE;
+  }
+
+  /* init the printing range */
+  packet_range_init(&args->range);
+
+  export_carrays_win = open_print_dialog("Wireshark: Export as \"C Arrays\" File",
+                                        output_action_export_carrays, args);
+  g_signal_connect(export_carrays_win, "destroy", G_CALLBACK(print_destroy_cb), &export_carrays_win);
+}
+#endif
+
+static void
+print_browse_file_cb(GtkWidget *file_bt, GtkWidget *file_te)
+{
+    file_selection_browse(file_bt, file_te, "Wireshark: Print to File",
+                          FILE_SELECTION_WRITE_BROWSE);
+}
+
+
+
+/* Open the print dialog */
+static GtkWidget *
+open_print_dialog(const char *title, output_action_e action, print_args_t *args)
+{
+  GtkWidget     *main_win;
   GtkWidget     *main_vb;
 
-  GtkWidget     *printer_fr, *printer_vb;
-  GtkWidget     *text_rb, *ps_rb, *pdml_rb, *psml_rb;
+  GtkWidget     *printer_fr, *printer_vb, *export_format_lb;
+  GtkWidget     *text_rb, *ps_rb, *pdml_rb, *psml_rb, *csv_rb, *carrays_rb;
   GtkWidget     *printer_tb, *dest_cb;
 #ifndef _WIN32
   GtkWidget     *cmd_lb, *cmd_te;
@@ -127,100 +520,84 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   GtkWidget     *hex_cb;
   GtkWidget     *sep, *formfeed_cb;
 
-  GtkWidget     *bbox, *ok_bt, *cancel_bt;
-
-  GtkTooltips   *tooltips;
-
-  print_args_t  *args = &print_args;
-
-  if (print_w != NULL) {
-    /* There's already a "Print" dialog box; reactivate it. */
-    reactivate_window(print_w);
-    return;
-  }
-
-  /* get settings from preferences (and other initial values) only once */
-  if(print_prefs_init == FALSE) {
-      print_prefs_init          = TRUE;
-      args->format              = prefs.pr_format;
-      args->to_file             = prefs.pr_dest;
-      args->file                = g_strdup(prefs.pr_file);
-      args->cmd                 = g_strdup(prefs.pr_cmd);
-      args->print_summary       = TRUE;
-      args->print_dissections   = print_dissections_as_displayed;
-      args->print_hex           = FALSE;
-      args->print_formfeed      = FALSE;
-  
-      /* init the printing range */
-      packet_range_init(&args->range);
-  }
-
-  /* Enable tooltips */
-  tooltips = gtk_tooltips_new();
+  GtkWidget     *bbox, *ok_bt, *cancel_bt, *help_bt;
 
   /* dialog window */
-  print_w = dlg_window_new("Ethereal: Print");
-  SIGNAL_CONNECT(print_w, "destroy", print_destroy_cb, NULL);
-
-#if GTK_MAJOR_VERSION < 2
-  /* Accelerator group for the accelerators (or, as they're called in
-     Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
-     Ctrl+<key> is an accelerator). */
-  accel_group = gtk_accel_group_new();
-  gtk_window_add_accel_group(GTK_WINDOW(print_w), accel_group);
-#endif
+  main_win = dlg_window_new(title);
 
   /* Vertical enclosing container for each row of widgets */
   main_vb = gtk_vbox_new(FALSE, 5);
-  gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
-  gtk_container_add(GTK_CONTAINER(print_w), main_vb);
+  gtk_container_set_border_width(GTK_CONTAINER(main_vb), 5);
+  gtk_container_add(GTK_CONTAINER(main_win), main_vb);
   gtk_widget_show(main_vb);
 
 /*****************************************************/
 
   /*** printer frame ***/
-  printer_fr = gtk_frame_new("Printer");
+  printer_fr = gtk_frame_new(action == output_action_print ? "Printer" : "Export to file:");
   gtk_box_pack_start(GTK_BOX(main_vb), printer_fr, FALSE, FALSE, 0);
   gtk_widget_show(printer_fr);
   printer_vb = gtk_vbox_new(FALSE, 5);
-  gtk_container_border_width(GTK_CONTAINER(printer_vb), 5);
+  gtk_container_set_border_width(GTK_CONTAINER(printer_vb), 5);
   gtk_container_add(GTK_CONTAINER(printer_fr), printer_vb);
   gtk_widget_show(printer_vb);
 
   /* "Plain text" / "Postscript" / "PDML", ... radio buttons */
-  text_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "Plain _text", accel_group);
+  text_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "Plain _text");
   if (args->format == PR_FMT_TEXT)
-    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(text_rb), TRUE);
-  gtk_tooltips_set_tip (tooltips, text_rb, ("Print output in ascii \"plain text\" format. If you're unsure, use this format."), NULL);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(text_rb), TRUE);
+  gtk_widget_set_tooltip_text(text_rb, "Print output in ascii \"plain text\" format. If you're unsure, use this format.");
   gtk_box_pack_start(GTK_BOX(printer_vb), text_rb, FALSE, FALSE, 0);
-  gtk_widget_show(text_rb);
+  if(action == output_action_print)
+    gtk_widget_show(text_rb);
 
-  ps_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "_PostScript", accel_group);
+  ps_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "_PostScript");
   if (args->format == PR_FMT_PS)
-    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ps_rb), TRUE);
-  gtk_tooltips_set_tip (tooltips, ps_rb, ("Print output in \"postscript\" format, for postscript capable printers or print servers."), NULL);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ps_rb), TRUE);
+  gtk_widget_set_tooltip_text(ps_rb, "Print output in \"postscript\" format, for postscript capable printers or print servers.");
   gtk_box_pack_start(GTK_BOX(printer_vb), ps_rb, FALSE, FALSE, 0);
-  gtk_widget_show(ps_rb);
+  if(action == output_action_print)
+    gtk_widget_show(ps_rb);
 
-  pdml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PDM_L (XML: Packet Details Markup Language)", accel_group);
-  if (args->format == PR_FMT_PDML)
-    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(pdml_rb), TRUE);
-  gtk_tooltips_set_tip (tooltips, pdml_rb, (
+  pdml_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "PDM_L (XML: Packet Details Markup Language)");
+  if (action == output_action_export_pdml)
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(pdml_rb), TRUE);
+  gtk_widget_set_tooltip_text(pdml_rb,
       "Print output in \"PDML\" (Packet Details Markup Language), "
       "an XML based packet data interchange format. "
-      "Usually used in combination with the \"Output to file\" option to export packet data into an XML file."), NULL);
+      "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.");
   gtk_box_pack_start(GTK_BOX(printer_vb), pdml_rb, FALSE, FALSE, 0);
-  gtk_widget_show(pdml_rb);
+  /* gtk_widget_show(pdml_rb); */
 
-  psml_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(text_rb, "PSML (XML: Packet Summary Markup Language)", accel_group);
-  if (args->format == PR_FMT_PSML)
-    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(psml_rb), TRUE);
-  gtk_tooltips_set_tip (tooltips, psml_rb, (
+  psml_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "PSML (XML: Packet Summary Markup Language)");
+  if (action == output_action_export_psml)
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(psml_rb), TRUE);
+  gtk_widget_set_tooltip_text(psml_rb,
       "Print output in \"PSML\" (Packet Summary Markup Language), "
       "an XML based packet summary interchange format. "
-      "Usually used in combination with the \"Output to file\" option to export packet data into an XML file."), NULL);
+      "Usually used in combination with the \"Output to file\" option to export packet data into an XML file.");
   gtk_box_pack_start(GTK_BOX(printer_vb), psml_rb, FALSE, FALSE, 0);
-  gtk_widget_show(psml_rb);
+  /* gtk_widget_show(psml_rb); */
+
+  csv_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "_CSV");
+  if (action == output_action_export_csv)
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(csv_rb), TRUE);
+  gtk_widget_set_tooltip_text(csv_rb,
+      "Print output in \"Comma Separated Values\" (CSV) format, "
+      "a text format compatible with OpenOffice and Excel. "
+      "One row for each packet, with its timestamp and size.");
+  gtk_box_pack_start(GTK_BOX(printer_vb), csv_rb, FALSE, FALSE, 0);
+  /* gtk_widget_show(csv_rb); */
+
+  carrays_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(text_rb), "C Arrays");
+  if (action == output_action_export_carrays)
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(carrays_rb), TRUE);
+  gtk_widget_set_tooltip_text(carrays_rb,
+      "Print output in C Arrays format, "
+      "a text file suitable for use in C/C++ programs. "
+      "One char[] for each packet.");
+  gtk_box_pack_start(GTK_BOX(printer_vb), carrays_rb, FALSE, FALSE, 0);
+  /* gtk_widget_show(carrays_rb); */
 
   /* printer table */
 #ifndef _WIN32
@@ -235,17 +612,18 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
 
 
   /* Output to file button */
-  dest_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Output to _file:", accel_group);
+  dest_cb = gtk_check_button_new_with_mnemonic("Output to _file:");
   if (args->to_file)
-    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
-  gtk_tooltips_set_tip (tooltips, dest_cb, ("Output to file instead of printer"), NULL);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
+  gtk_widget_set_tooltip_text(dest_cb, "Output to file instead of printer");
   gtk_table_attach_defaults(GTK_TABLE(printer_tb), dest_cb, 0, 1, 0, 1);
-  gtk_widget_show(dest_cb);
-  
-  /* File text entry and "Browse" button */
+  if(action == output_action_print)
+    gtk_widget_show(dest_cb);
+
+  /* File text entry */
   file_te = gtk_entry_new();
-  OBJECT_SET_DATA(dest_cb, PRINT_FILE_TE_KEY, file_te);
-  gtk_tooltips_set_tip (tooltips, file_te, ("Enter Output filename"), NULL);
+  g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_TE_KEY, file_te);
+  gtk_widget_set_tooltip_text(file_te, "Enter Output filename");
   gtk_entry_set_text(GTK_ENTRY(file_te), args->file);
   gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_te, 1, 2, 0, 1);
   gtk_widget_set_sensitive(file_te, args->to_file);
@@ -253,10 +631,11 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   if (args->to_file)
     gtk_widget_grab_focus(file_te);
 
-  file_bt = BUTTON_NEW_FROM_STOCK(ETHEREAL_STOCK_BROWSE);
-  OBJECT_SET_DATA(dest_cb, PRINT_FILE_BT_KEY, file_bt);
-  OBJECT_SET_DATA(file_bt, E_FILE_TE_PTR_KEY, file_te);
-  gtk_tooltips_set_tip (tooltips, file_bt, ("Browse output filename in filesystem"), NULL);
+  /* "Browse" button */
+  file_bt = gtk_button_new_from_stock(WIRESHARK_STOCK_BROWSE);
+  g_object_set_data(G_OBJECT(dest_cb), PRINT_FILE_BT_KEY, file_bt);
+  g_object_set_data(G_OBJECT(file_bt), PRINT_TE_PTR_KEY, file_te);
+  gtk_widget_set_tooltip_text(file_bt, "Browse output filename in filesystem");
   gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_bt, 2, 3, 0, 1);
   gtk_widget_set_sensitive(file_bt, args->to_file);
   gtk_widget_show(file_bt);
@@ -264,24 +643,31 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   /* Command label and text entry */
 #ifndef _WIN32
   cmd_lb = gtk_label_new("Print command:");
-  OBJECT_SET_DATA(dest_cb, PRINT_CMD_LB_KEY, cmd_lb);
-  gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
+  g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_LB_KEY, cmd_lb);
+  gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0f, 0.5f);
   gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_lb, 0, 1, 1, 2);
   gtk_widget_set_sensitive(cmd_lb, !args->to_file);
-  gtk_widget_show(cmd_lb);
+  if(action == output_action_print)
+    gtk_widget_show(cmd_lb);
 
   cmd_te = gtk_entry_new();
-  OBJECT_SET_DATA(dest_cb, PRINT_CMD_TE_KEY, cmd_te);
-  gtk_tooltips_set_tip (tooltips, cmd_te, ("Enter print command"), NULL);
+  g_object_set_data(G_OBJECT(dest_cb), PRINT_CMD_TE_KEY, cmd_te);
+  gtk_widget_set_tooltip_text(cmd_te, "Enter print command");
   gtk_entry_set_text(GTK_ENTRY(cmd_te), args->cmd);
   gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_te, 1, 2, 1, 2);
   gtk_widget_set_sensitive(cmd_te, !args->to_file);
-  gtk_widget_show(cmd_te);
+  if(action == output_action_print)
+    gtk_widget_show(cmd_te);
 #endif
 
-  SIGNAL_CONNECT(dest_cb, "toggled", print_cmd_toggle_dest, NULL);
-  SIGNAL_CONNECT(file_bt, "clicked", select_file_cb, "Ethereal: Print to File");
+  g_signal_connect(dest_cb, "toggled", G_CALLBACK(print_cmd_toggle_dest), NULL);
+  g_signal_connect(file_bt, "clicked", G_CALLBACK(print_browse_file_cb), file_te);
 
+  if(action == output_action_export_ps) {
+    export_format_lb = gtk_label_new("(PostScript files can be easily converted to PDF files using ghostscript's ps2pdf)");
+    gtk_box_pack_start(GTK_BOX(printer_vb), export_format_lb, FALSE, FALSE, 0);
+    gtk_widget_show(export_format_lb);
+  }
 
 /*****************************************************/
 
@@ -295,11 +681,7 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   gtk_box_pack_start(GTK_BOX(packet_hb), range_fr, FALSE, FALSE, 0);
   gtk_widget_show(range_fr);
 
-  range_tb = range_new(&args->range
-#if GTK_MAJOR_VERSION < 2
-  , accel_group
-#endif
-  );
+  range_tb = range_new(&args->range);
   gtk_container_add(GTK_CONTAINER(range_fr), range_tb);
   gtk_widget_show(range_tb);
 
@@ -308,69 +690,72 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   /*** packet format frame ***/
   format_fr = gtk_frame_new("Packet Format");
   gtk_box_pack_start(GTK_BOX(packet_hb), format_fr, TRUE, TRUE, 0);
-  gtk_widget_show(format_fr);
+  if(   action == output_action_print ||
+        action == output_action_export_text ||
+        action == output_action_export_ps)
+    gtk_widget_show(format_fr);
   format_vb = gtk_vbox_new(FALSE, 5);
-  gtk_container_border_width(GTK_CONTAINER(format_vb), 5);
+  gtk_container_set_border_width(GTK_CONTAINER(format_vb), 5);
   gtk_container_add(GTK_CONTAINER(format_fr), format_vb);
   gtk_widget_show(format_vb);
 
   /* "Print summary line" check button */
-  summary_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Packet summary line", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(summary_cb), args->print_summary);
-  SIGNAL_CONNECT(summary_cb, "clicked", print_cmd_toggle_detail, print_w);
-  gtk_tooltips_set_tip (tooltips, summary_cb, ("Output of a packet summary line, like in the packet list"), NULL);
+  summary_cb = gtk_check_button_new_with_mnemonic("Packet summary line");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(summary_cb), args->print_summary);
+  g_signal_connect(summary_cb, "clicked", G_CALLBACK(print_cmd_toggle_detail), main_win);
+  gtk_widget_set_tooltip_text(summary_cb, "Output of a packet summary line, like in the packet list");
   gtk_container_add(GTK_CONTAINER(format_vb), summary_cb);
   gtk_widget_show(summary_cb);
 
 
   /* "Details" check button */
-  details_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Packet details:", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(details_cb), args->print_dissections != print_dissections_none);
-  SIGNAL_CONNECT(details_cb, "clicked", print_cmd_toggle_detail, print_w);
-  gtk_tooltips_set_tip (tooltips, details_cb, ("Output format of the selected packet details (protocol tree)."), NULL);
+  details_cb = gtk_check_button_new_with_mnemonic("Packet details:");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(details_cb), args->print_dissections != print_dissections_none);
+  g_signal_connect(details_cb, "clicked", G_CALLBACK(print_cmd_toggle_detail), main_win);
+  gtk_widget_set_tooltip_text(details_cb, "Output format of the selected packet details (protocol tree).");
   gtk_container_add(GTK_CONTAINER(format_vb), details_cb);
   gtk_widget_show(details_cb);
 
   /*** packet details ***/
   details_hb = gtk_hbox_new(FALSE, 6);
-  gtk_container_border_width(GTK_CONTAINER(details_hb), 0);
+  gtk_container_set_border_width(GTK_CONTAINER(details_hb), 0);
   gtk_container_add(GTK_CONTAINER(format_vb), details_hb);
   gtk_widget_show(details_hb);
 
   details_vb = gtk_vbox_new(FALSE, 6);
-  gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
+  gtk_container_set_border_width(GTK_CONTAINER(details_vb), 0);
   gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
   gtk_widget_show(details_vb);
 
   details_vb = gtk_vbox_new(FALSE, 6);
-  gtk_container_border_width(GTK_CONTAINER(details_vb), 0);
+  gtk_container_set_border_width(GTK_CONTAINER(details_vb), 0);
   gtk_container_add(GTK_CONTAINER(details_hb), details_vb);
   gtk_widget_show(details_vb);
 
   /* "All collapsed"/"As displayed"/"All Expanded" radio buttons */
-  collapse_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(NULL, "All co_llapsed", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(collapse_all_rb), args->print_dissections == print_dissections_collapsed);
-  gtk_tooltips_set_tip (tooltips, collapse_all_rb, ("Output of the packet details tree \"collapsed\""), NULL);
+  collapse_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(NULL, "All co_llapsed");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(collapse_all_rb), args->print_dissections == print_dissections_collapsed);
+  gtk_widget_set_tooltip_text(collapse_all_rb, "Output of the packet details tree \"collapsed\"");
   gtk_container_add(GTK_CONTAINER(details_vb), collapse_all_rb);
   gtk_widget_show(collapse_all_rb);
 
-  as_displayed_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "As displa_yed", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(as_displayed_rb), args->print_dissections == print_dissections_as_displayed);
-  gtk_tooltips_set_tip (tooltips, as_displayed_rb, ("Output of the packet details tree \"as displayed\""), NULL);
+  as_displayed_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(collapse_all_rb), "As displa_yed");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(as_displayed_rb), args->print_dissections == print_dissections_as_displayed);
+  gtk_widget_set_tooltip_text(as_displayed_rb, "Output of the packet details tree \"as displayed\"");
   gtk_container_add(GTK_CONTAINER(details_vb), as_displayed_rb);
   gtk_widget_show(as_displayed_rb);
 
-  expand_all_rb = RADIO_BUTTON_NEW_WITH_MNEMONIC(collapse_all_rb, "All e_xpanded", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(expand_all_rb), args->print_dissections == print_dissections_expanded);
-  gtk_tooltips_set_tip (tooltips, expand_all_rb, ("Output of the packet details tree \"expanded\""), NULL);
+  expand_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(GTK_RADIO_BUTTON(collapse_all_rb), "All e_xpanded");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(expand_all_rb), args->print_dissections == print_dissections_expanded);
+  gtk_widget_set_tooltip_text(expand_all_rb, "Output of the packet details tree \"expanded\"");
   gtk_container_add(GTK_CONTAINER(details_vb), expand_all_rb);
   gtk_widget_show(expand_all_rb);
 
   /* "Print hex" check button. */
-  hex_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Packet bytes", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_cb), args->print_hex);
-  SIGNAL_CONNECT(hex_cb, "clicked", print_cmd_toggle_detail, print_w);
-  gtk_tooltips_set_tip (tooltips, hex_cb, ("Add a hexdump of the packet data"), NULL);
+  hex_cb = gtk_check_button_new_with_mnemonic("Packet bytes");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(hex_cb), args->print_hex);
+  g_signal_connect(hex_cb, "clicked", G_CALLBACK(print_cmd_toggle_detail), main_win);
+  gtk_widget_set_tooltip_text(hex_cb, "Add a hexdump of the packet data");
   gtk_container_add(GTK_CONTAINER(format_vb), hex_cb);
   gtk_widget_show(hex_cb);
 
@@ -380,75 +765,91 @@ file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
   gtk_widget_show(sep);
 
   /* "Each packet on a new page" check button. */
-  formfeed_cb = CHECK_BUTTON_NEW_WITH_MNEMONIC("Each packet on a new page", accel_group);
-  gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(formfeed_cb), args->print_formfeed);
-  gtk_tooltips_set_tip (tooltips, formfeed_cb, ("When checked, a new page will be used for each packet. "
-      "This is done by adding a formfeed (or similar) between the packet outputs."), NULL);
+  formfeed_cb = gtk_check_button_new_with_mnemonic("Each packet on a new page");
+  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(formfeed_cb), args->print_formfeed);
+  gtk_widget_set_tooltip_text (formfeed_cb, "When checked, a new page will be used for each packet. "
+      "This is done by adding a formfeed (or similar) between the packet outputs.");
   gtk_container_add(GTK_CONTAINER(format_vb), formfeed_cb);
   gtk_widget_show(formfeed_cb);
 
 
-  OBJECT_SET_DATA(print_w, PRINT_ARGS_KEY, args);
-  OBJECT_SET_DATA(print_w, PRINT_SUMMARY_CB_KEY, summary_cb);
-  OBJECT_SET_DATA(print_w, PRINT_DETAILS_CB_KEY, details_cb);
-  OBJECT_SET_DATA(print_w, PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
-  OBJECT_SET_DATA(print_w, PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
-  OBJECT_SET_DATA(print_w, PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
-  OBJECT_SET_DATA(print_w, PRINT_HEX_CB_KEY, hex_cb);
+  g_object_set_data(G_OBJECT(main_win), PRINT_ARGS_KEY, args);
+  g_object_set_data(G_OBJECT(main_win), PRINT_SUMMARY_CB_KEY, summary_cb);
+  g_object_set_data(G_OBJECT(main_win), PRINT_DETAILS_CB_KEY, details_cb);
+  g_object_set_data(G_OBJECT(main_win), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
+  g_object_set_data(G_OBJECT(main_win), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
+  g_object_set_data(G_OBJECT(main_win), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
+  g_object_set_data(G_OBJECT(main_win), PRINT_HEX_CB_KEY, hex_cb);
 
 /*****************************************************/
 
 
   /* Button row */
-  bbox = dlg_button_row_new(GTK_STOCK_PRINT, GTK_STOCK_CANCEL, NULL);
+  bbox = dlg_button_row_new(action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK, GTK_STOCK_CANCEL, GTK_STOCK_HELP, NULL);
   gtk_box_pack_start(GTK_BOX(main_vb), bbox, FALSE, FALSE, 0);
   gtk_widget_show(bbox);
 
-  ok_bt = OBJECT_GET_DATA(bbox, GTK_STOCK_PRINT);
+  ok_bt = g_object_get_data(G_OBJECT(bbox), action == output_action_print ? GTK_STOCK_PRINT : GTK_STOCK_OK);
 
-  OBJECT_SET_DATA(print_w, PRINT_BT_KEY, ok_bt);
+  g_object_set_data(G_OBJECT(main_win), PRINT_BT_KEY, ok_bt);
 
-  OBJECT_SET_DATA(ok_bt, PRINT_PS_RB_KEY, ps_rb);
-  OBJECT_SET_DATA(ok_bt, PRINT_PDML_RB_KEY, pdml_rb);
-  OBJECT_SET_DATA(ok_bt, PRINT_PSML_RB_KEY, psml_rb);
-  OBJECT_SET_DATA(ok_bt, PRINT_DEST_CB_KEY, dest_cb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY, ps_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY, pdml_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY, psml_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY, csv_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY, carrays_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY, dest_cb);
 #ifndef _WIN32
-  OBJECT_SET_DATA(ok_bt, PRINT_CMD_TE_KEY, cmd_te);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
 #endif
 
-  OBJECT_SET_DATA(ok_bt, PRINT_ARGS_KEY, args);
-  OBJECT_SET_DATA(ok_bt, PRINT_FILE_TE_KEY, file_te);
-  OBJECT_SET_DATA(ok_bt, PRINT_SUMMARY_CB_KEY, summary_cb);
-  OBJECT_SET_DATA(ok_bt, PRINT_DETAILS_CB_KEY, details_cb);
-  OBJECT_SET_DATA(ok_bt, PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
-  OBJECT_SET_DATA(ok_bt, PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
-  OBJECT_SET_DATA(ok_bt, PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
-  OBJECT_SET_DATA(ok_bt, PRINT_HEX_CB_KEY, hex_cb);
-  OBJECT_SET_DATA(ok_bt, PRINT_FORMFEED_CB_KEY, formfeed_cb);
-  SIGNAL_CONNECT(ok_bt, "clicked", print_ok_cb, print_w);
-  gtk_tooltips_set_tip (tooltips, ok_bt, ("Start printing"), NULL);
-  gtk_widget_grab_default(ok_bt);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY, args);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY, summary_cb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY, details_cb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY, hex_cb);
+  g_object_set_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY, formfeed_cb);
+  g_signal_connect(ok_bt, "clicked", G_CALLBACK(print_ok_cb), main_win);
+  gtk_widget_set_tooltip_text (ok_bt, "Start output");
+
+  cancel_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_CANCEL);
+  window_set_cancel_button(main_win, cancel_bt, window_cancel_button_cb);
+  gtk_widget_set_tooltip_text (cancel_bt, "Cancel and exit dialog");
+
+  if(action == output_action_print) {
+    help_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+    g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_PRINT_DIALOG);
+  } else {
+#ifdef _WIN32
+    help_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+    g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_EXPORT_FILE_WIN32_DIALOG);
+#else
+    help_bt  = g_object_get_data(G_OBJECT(bbox), GTK_STOCK_HELP);
+    g_signal_connect(help_bt, "clicked", G_CALLBACK(topic_cb), (gpointer)HELP_EXPORT_FILE_DIALOG);
+#endif
+  }
 
-  cancel_bt  = OBJECT_GET_DATA(bbox, GTK_STOCK_CANCEL);
-  SIGNAL_CONNECT(cancel_bt, "clicked", print_close_cb, print_w);
-  gtk_tooltips_set_tip (tooltips, cancel_bt, ("Cancel print and exit dialog"), NULL);
+  gtk_widget_grab_default(ok_bt);
 
   /* Catch the "activate" signal on the "Command" and "File" text entries,
      so that if the user types Return there, we act as if the "OK" button
      had been selected, as happens if Return is typed if some widget
      that *doesn't* handle the Return key has the input focus. */
-
 #ifndef _WIN32
   dlg_set_activate(cmd_te, ok_bt);
 #endif
-  dlg_set_activate(file_te, ok_bt);
+  if(action != output_action_print)
+    dlg_set_activate(file_te, ok_bt);
 
-  /* Catch the "key_press_event" signal in the window, so that we can catch
-     the ESC key being pressed and act as if the "Cancel" button had
-     been selected. */
-  dlg_set_cancel(print_w, cancel_bt);
+  g_signal_connect(main_win, "delete_event", G_CALLBACK(window_delete_event_cb), NULL);
 
-  gtk_widget_show(print_w);
+  gtk_widget_show(main_win);
+  window_present(main_win);
+
+  return main_win;
 }
 
 
@@ -463,11 +864,11 @@ print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
   int            to_file;
 
 #ifndef _WIN32
-  cmd_lb = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_CMD_LB_KEY));
-  cmd_te = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_CMD_TE_KEY));
+  cmd_lb = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_LB_KEY));
+  cmd_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_CMD_TE_KEY));
 #endif
-  file_bt = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_FILE_BT_KEY));
-  file_te = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_FILE_TE_KEY));
+  file_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_BT_KEY));
+  file_te = GTK_WIDGET(g_object_get_data(G_OBJECT(widget), PRINT_FILE_TE_KEY));
 
   to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (widget));
 #ifndef _WIN32
@@ -487,13 +888,13 @@ print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
   gboolean      print_detail;
 
 
-  print_bt = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_BT_KEY));
-  summary_cb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_SUMMARY_CB_KEY));
-  details_cb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_DETAILS_CB_KEY));
-  collapse_all_rb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_COLLAPSE_ALL_RB_KEY));
-  as_displayed_rb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_AS_DISPLAYED_RB_KEY));
-  expand_all_rb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_EXPAND_ALL_RB_KEY));
-  hex_cb = GTK_WIDGET(OBJECT_GET_DATA(data, PRINT_HEX_CB_KEY));
+  print_bt = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_BT_KEY));
+  summary_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_SUMMARY_CB_KEY));
+  details_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_DETAILS_CB_KEY));
+  collapse_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_COLLAPSE_ALL_RB_KEY));
+  as_displayed_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_AS_DISPLAYED_RB_KEY));
+  expand_all_rb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_EXPAND_ALL_RB_KEY));
+  hex_cb = GTK_WIDGET(g_object_get_data(G_OBJECT(data), PRINT_HEX_CB_KEY));
 
   /* is user disabled details, disable the corresponding buttons */
   print_detail = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb));
@@ -502,7 +903,7 @@ print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
   gtk_widget_set_sensitive(expand_all_rb, print_detail);
 
   /* if user selected nothing to print at all, disable the "ok" button */
-  gtk_widget_set_sensitive(print_bt, 
+  gtk_widget_set_sensitive(print_bt,
       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (summary_cb)) ||
       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (details_cb)) ||
       gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (hex_cb)));
@@ -512,26 +913,41 @@ print_cmd_toggle_detail(GtkWidget *widget _U_, gpointer data)
 static void
 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
 {
-  GtkWidget     *button;
-  print_args_t  *args;
-  const gchar   *g_dest;
-  gchar         *f_name;
-  gchar         *dirname;
+  GtkWidget         *button;
+  print_args_t      *args;
+  const gchar       *g_dest;
+  gchar             *f_name;
+  gchar             *dirname;
+  gboolean          export_as_pdml = FALSE, export_as_psml = FALSE;
+  gboolean          export_as_csv = FALSE;
+  gboolean          export_as_carrays = FALSE;
 #ifdef _WIN32
-  int win_printer_flag = FALSE;
+  gboolean          win_printer = FALSE;
+  int               tmp_fd;
+  char              *tmp_namebuf;
+  char              *tmp_oldfile = NULL;
 #endif
+  cf_print_status_t status;
+
+  args = (print_args_t *)g_object_get_data(G_OBJECT(ok_bt), PRINT_ARGS_KEY);
 
-  args = (print_args_t *)OBJECT_GET_DATA(ok_bt, PRINT_ARGS_KEY);
+  /* Check whether the range is valid. */
+  if (!range_check_validity(&args->range)) {
+    /* The range isn't valid; don't dismiss the print/export dialog box,
+       just leave it around so that the user can, after they
+       dismiss the alert box popped up for the error, try again. */
+    return;
+  }
 
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DEST_CB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DEST_CB_KEY);
   args->to_file = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
 
   if (args->to_file) {
-    g_dest = gtk_entry_get_text(GTK_ENTRY(OBJECT_GET_DATA(ok_bt,
+      g_dest = gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
                                                           PRINT_FILE_TE_KEY)));
     if (!g_dest[0]) {
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-        "Printing to file, but no file specified.");
+        "Output to file, but no file specified.");
       return;
     }
     g_free(args->file);
@@ -543,67 +959,136 @@ print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
     g_free(f_name);
   } else {
 #ifdef _WIN32
-    win_printer_flag = TRUE;
-    /*XXX should use temp file stuff in util routines */
-    g_free(args->file);
-    args->file = g_strdup(tmpnam(NULL));
+    win_printer = TRUE;
+    /* We currently don't have a function in util.h to create just a tempfile */
+    /* name, so simply create a tempfile using the "official" function,       */
+    /* then delete this file again. After this, the name MUST be available.   */
+    /* */
+    /* Don't use tmpnam() or such, as this will fail under some ACL           */
+    /* circumstances: http://bugs.wireshark.org/bugzilla/show_bug.cgi?id=358  */
+    /* Also: tmpnam is "insecure" and should not be used.                     */
+    tmp_fd = create_tempfile(&tmp_namebuf, "wshprint");
+    if(tmp_fd == -1) {
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+            "Couldn't create a temporary file for printing:\n%s", tmp_namebuf);
+        return;
+    }
+    /* remember to restore these values later! */
+    tmp_oldfile = args->file;
+    args->file = g_strdup(tmp_namebuf);
+    ws_unlink(args->file);
     args->to_file = TRUE;
 #else
     g_free(args->cmd);
-    args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(OBJECT_GET_DATA(ok_bt,
+    args->cmd = g_strdup(gtk_entry_get_text(GTK_ENTRY(g_object_get_data(G_OBJECT(ok_bt),
       PRINT_CMD_TE_KEY))));
 #endif
   }
 
   args->format = PR_FMT_TEXT;
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_PS_RB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PS_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
     args->format = PR_FMT_PS;
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_PDML_RB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PDML_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
-    args->format = PR_FMT_PDML;
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_PSML_RB_KEY);
+    export_as_pdml = TRUE;
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_PSML_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
-    args->format = PR_FMT_PSML;
+    export_as_psml = TRUE;
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CSV_RB_KEY);
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
+    export_as_csv = TRUE;
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_CARRAYS_RB_KEY);
+  if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button)))
+    export_as_carrays = TRUE;
 
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_SUMMARY_CB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_SUMMARY_CB_KEY);
   args->print_summary = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
 
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_COLLAPSE_ALL_RB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_COLLAPSE_ALL_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
     args->print_dissections = print_dissections_collapsed;
   }
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_AS_DISPLAYED_RB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_AS_DISPLAYED_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
     args->print_dissections = print_dissections_as_displayed;
   }
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_EXPAND_ALL_RB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY);
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
     args->print_dissections = print_dissections_expanded;
   }
 
   /* the details setting has priority over the radio buttons */
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DETAILS_CB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_DETAILS_CB_KEY);
   if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button))) {
     args->print_dissections = print_dissections_none;
   }
 
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_HEX_CB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_HEX_CB_KEY);
   args->print_hex = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
 
-  button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_FORMFEED_CB_KEY);
+  button = (GtkWidget *)g_object_get_data(G_OBJECT(ok_bt), PRINT_FORMFEED_CB_KEY);
   args->print_formfeed = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON (button));
 
 
-  gtk_widget_destroy(GTK_WIDGET(parent_w));
-
-  /* Now print the packets */
-  switch (print_packets(&cfile, args)) {
+  window_destroy(GTK_WIDGET(parent_w));
+
+  /* Now print/export the packets */
+  if (export_as_pdml)
+    status = cf_write_pdml_packets(&cfile, args);
+  else if (export_as_psml)
+    status = cf_write_psml_packets(&cfile, args);
+  else if (export_as_csv)
+    status = cf_write_csv_packets(&cfile, args);
+  else if (export_as_carrays)
+    status = cf_write_carrays_packets(&cfile, args);
+  else {
+    switch (args->format) {
+
+    case PR_FMT_TEXT:
+      if (args->to_file) {
+        args->stream = print_stream_text_new(TRUE, args->file);
+        if (args->stream == NULL) {
+          open_failure_alert_box(args->file, errno, TRUE);
+          return;
+        }
+      } else {
+        args->stream = print_stream_text_new(FALSE, args->cmd);
+        if (args->stream == NULL) {
+          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                        "Couldn't run print command %s.", args->cmd);
+        }
+      }
+      break;
+
+    case PR_FMT_PS:
+      if (args->to_file) {
+        args->stream = print_stream_ps_new(TRUE, args->file);
+        if (args->stream == NULL) {
+          open_failure_alert_box(args->file, errno, TRUE);
+          return;
+        }
+      } else {
+        args->stream = print_stream_ps_new(FALSE, args->cmd);
+        if (args->stream == NULL) {
+          simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
+                        "Couldn't run print command %s.", args->cmd);
+        }
+      }
+      break;
+
+    default:
+      g_assert_not_reached();
+      return;
+    }
+    status = cf_print_packets(&cfile, args);
+  }
+  switch (status) {
 
-  case PP_OK:
+  case CF_PRINT_OK:
     break;
 
-  case PP_OPEN_ERROR:
+  case CF_PRINT_OPEN_ERROR:
     if (args->to_file)
       open_failure_alert_box(args->file, errno, TRUE);
     else
@@ -611,50 +1096,44 @@ print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
         args->cmd);
     break;
 
-  case PP_WRITE_ERROR:
+  case CF_PRINT_WRITE_ERROR:
     if (args->to_file)
       write_failure_alert_box(args->file, errno);
     else
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
-       "Error writing to print command: %s", strerror(errno));
+       "Error writing to print command: %s", g_strerror(errno));
     break;
   }
 
 #ifdef _WIN32
-  if (win_printer_flag) {
+  if (win_printer) {
     print_mswin(args->file);
 
     /* trash temp file */
-    remove(args->file);
+    ws_remove(args->file);
+    g_free(args->file);
+
+    /* restore old settings */
+    args->to_file = FALSE;
+    args->file = tmp_oldfile;
   }
 #endif
 }
 
 static void
-print_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
-{
-  gtk_grab_remove(GTK_WIDGET(parent_w));
-  gtk_widget_destroy(GTK_WIDGET(parent_w));
-}
-
-static void
-print_destroy_cb(GtkWidget *win, gpointer user_data _U_)
+print_destroy_cb(GtkWidget *win, gpointer user_data)
 {
   GtkWidget     *fs;
 
   /* Is there a file selection dialog associated with this
      Print File dialog? */
-  fs = OBJECT_GET_DATA(win, E_FILE_SEL_DIALOG_PTR_KEY);
+  fs = g_object_get_data(G_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
 
   if (fs != NULL) {
     /* Yes.  Destroy it. */
-    gtk_widget_destroy(fs);
+    window_destroy(fs);
   }
 
   /* Note that we no longer have a "Print" dialog box. */
-  print_w = NULL;
+  *((gpointer *) user_data) = NULL;
 }
-
-
-
-