Added two new arguments to epan_init() and proto_init() to
[obnox/wireshark/wip.git] / gtk / print_dlg.c
1 /* print_dlg.c
2  * Dialog boxes for printing
3  *
4  * $Id: print_dlg.c,v 1.22 2000/11/21 23:54:10 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <errno.h>
31
32 #include <gtk/gtk.h>
33
34 #include "globals.h"
35 #include "keys.h"
36 #include "print.h"
37 #include "prefs_dlg.h"
38 #include "simple_dialog.h"
39 #include "ui_util.h"
40 #include "dlg_utils.h"
41
42 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
43 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
44 static void print_file_cb(GtkWidget *file_bt, gpointer file_te);
45 static void print_fs_ok_cb(GtkWidget *w, gpointer data);
46 static void print_fs_cancel_cb(GtkWidget *w, gpointer data);
47 static void print_fs_destroy_cb(GtkWidget *win, gpointer data);
48 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
49 static void print_close_cb(GtkWidget *close_bt, gpointer parent_w);
50 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
51
52 /*
53  * Remember whether we printed to a printer or a file the last time we
54  * printed something.
55  */
56 static int     print_to_file;
57
58 /*
59  * Remember whether we printed as text or PostScript the last time we
60  * printed something.
61  */
62 static gint     print_format = PR_FMT_TEXT;
63
64 #define PRINT_FORMAT_RB_KEY       "printer_format_radio_button"
65 #define PRINT_DEST_RB_KEY         "printer_destination_radio_button"
66
67 #define PRINT_SUMMARY_RB_KEY      "printer_summary_radio_button"
68 #define PRINT_HEX_CB_KEY          "printer_hex_check_button"
69 #define PRINT_EXPAND_ALL_RB_KEY   "printer_expand_all_radio_button"
70 #define PRINT_AS_DISPLAYED_RB_KEY "printer_as_displayed_radio_button"
71
72 #define E_FS_CALLER_PTR_KEY       "fs_caller_ptr"
73 #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr"
74
75 /*
76  * Keep a static pointer to the current "Print" window, if any, so that if
77  * somebody tries to do "File:Print" while there's already a "Print" window
78  * up, we just pop up the existing one, rather than creating a new one.
79  */
80 static GtkWidget *print_w;
81
82 /* Print the capture */
83 void
84 file_print_cmd_cb(GtkWidget *widget, gpointer data)
85 {
86   GtkAccelGroup *accel_group;
87   GtkWidget     *main_vb, *main_tb, *button;
88   GtkWidget     *format_rb;
89   GtkWidget     *format_hb, *format_lb;
90   GSList        *format_grp;
91   GtkWidget     *dest_rb;
92   GtkWidget     *dest_hb, *dest_lb;
93   GtkWidget     *cmd_lb, *cmd_te;
94   GtkWidget     *file_bt_hb, *file_bt, *file_te;
95   GSList        *dest_grp;
96   GtkWidget     *options_hb;
97   GtkWidget     *print_type_vb, *summary_rb, *detail_rb, *hex_cb;
98   GSList        *summary_grp;
99   GtkWidget     *expand_vb, *expand_all_rb, *as_displayed_rb;
100   GSList        *expand_grp;
101   GtkWidget     *bbox, *ok_bt, *cancel_bt;
102
103   if (print_w != NULL) {
104     /* There's already a "Print" dialog box; reactivate it. */
105     reactivate_window(print_w);
106     return;
107   }
108
109   print_w = dlg_window_new("Ethereal: Print");
110   gtk_signal_connect(GTK_OBJECT(print_w), "destroy",
111         GTK_SIGNAL_FUNC(print_destroy_cb), NULL);
112
113   /* Accelerator group for the accelerators (or, as they're called in
114      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
115      Ctrl+<key> is an accelerator). */
116   accel_group = gtk_accel_group_new();
117   gtk_window_add_accel_group(GTK_WINDOW(print_w), accel_group);
118
119   /* Enclosing containers for each row of widgets */
120   main_vb = gtk_vbox_new(FALSE, 5);
121   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
122   gtk_container_add(GTK_CONTAINER(print_w), main_vb);
123   gtk_widget_show(main_vb);
124   
125   main_tb = gtk_table_new(4, 2, FALSE);
126   gtk_box_pack_start(GTK_BOX(main_vb), main_tb, FALSE, FALSE, 0);
127   gtk_table_set_row_spacings(GTK_TABLE(main_tb), 10);
128   gtk_table_set_col_spacings(GTK_TABLE(main_tb), 15);
129   gtk_widget_show(main_tb);
130
131   /* Output format */
132   format_lb = gtk_label_new("Format:");
133   gtk_misc_set_alignment(GTK_MISC(format_lb), 1.0, 0.5);
134   gtk_table_attach_defaults(GTK_TABLE(main_tb), format_lb, 0, 1, 0, 1);
135   gtk_widget_show(format_lb);
136
137   format_hb = gtk_hbox_new(FALSE, 0);
138   gtk_table_attach_defaults(GTK_TABLE(main_tb), format_hb, 1, 2, 0, 1);
139   gtk_widget_show(format_hb);
140
141   button = dlg_radio_button_new_with_label_with_mnemonic(NULL, "Plain _Text",
142                                 accel_group);
143   if (print_format == PR_FMT_TEXT)
144     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
145   format_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
146   gtk_box_pack_start(GTK_BOX(format_hb), button, FALSE, FALSE, 10);
147   gtk_widget_show(button);
148
149   format_rb = dlg_radio_button_new_with_label_with_mnemonic(format_grp,
150                                 "_PostScript", accel_group);
151   if (print_format == PR_FMT_PS)
152     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(format_rb), TRUE);
153   gtk_box_pack_start(GTK_BOX(format_hb), format_rb, FALSE, FALSE, 10);
154   gtk_widget_show(format_rb);
155
156   /* Output destination */
157   dest_lb = gtk_label_new("Print to:");
158   gtk_misc_set_alignment(GTK_MISC(dest_lb), 1.0, 0.5);
159   gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_lb, 0, 1, 1, 2);
160   gtk_widget_show(dest_lb);
161
162   dest_hb = gtk_hbox_new(FALSE, 0);
163   gtk_table_attach_defaults(GTK_TABLE(main_tb), dest_hb, 1, 2, 1, 2);
164   gtk_widget_show(dest_hb);
165
166   button = dlg_radio_button_new_with_label_with_mnemonic(NULL, "_Command",
167                                 accel_group);
168   if (!print_to_file)
169     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(button), TRUE);
170   dest_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(button));
171   gtk_box_pack_start(GTK_BOX(dest_hb), button, FALSE, FALSE, 10);
172   gtk_widget_show(button);
173
174   dest_rb = dlg_radio_button_new_with_label_with_mnemonic(dest_grp, "_File",
175                                 accel_group);
176   if (print_to_file)
177     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_rb), TRUE);
178   gtk_signal_connect(GTK_OBJECT(dest_rb), "toggled",
179                         GTK_SIGNAL_FUNC(print_cmd_toggle_dest), NULL);
180   gtk_box_pack_start(GTK_BOX(dest_hb), dest_rb, FALSE, FALSE, 10);
181   gtk_widget_show(dest_rb);
182
183   /* Command text entry */
184   cmd_lb = gtk_label_new("Command:");
185   gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_LB_KEY, cmd_lb);
186   gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
187   gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_lb, 0, 1, 2, 3);
188   gtk_widget_set_sensitive(cmd_lb, !print_to_file);
189   gtk_widget_show(cmd_lb);
190
191   cmd_te = gtk_entry_new();
192   gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_CMD_TE_KEY, cmd_te);
193   if (prefs.pr_cmd)
194     gtk_entry_set_text(GTK_ENTRY(cmd_te), prefs.pr_cmd);
195   gtk_table_attach_defaults(GTK_TABLE(main_tb), cmd_te, 1, 2, 2, 3);
196   gtk_widget_set_sensitive(cmd_te, !print_to_file);
197   gtk_widget_show(cmd_te);
198
199   /* File button and text entry */
200   file_bt_hb = gtk_hbox_new(FALSE, 0);
201   gtk_table_attach_defaults(GTK_TABLE(main_tb), file_bt_hb, 0, 1, 3, 4);
202   gtk_widget_show(file_bt_hb);
203
204   file_bt = gtk_button_new_with_label("File:");
205   gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_BT_KEY, file_bt);
206   gtk_box_pack_end(GTK_BOX(file_bt_hb), file_bt, FALSE, FALSE, 0);
207   gtk_widget_set_sensitive(file_bt, print_to_file);
208   gtk_widget_show(file_bt);
209
210   file_te = gtk_entry_new();
211   gtk_object_set_data(GTK_OBJECT(dest_rb), PRINT_FILE_TE_KEY, file_te);
212   gtk_table_attach_defaults(GTK_TABLE(main_tb), file_te, 1, 2, 3, 4);
213   gtk_widget_set_sensitive(file_te, print_to_file);
214   gtk_widget_show(file_te);
215
216   gtk_signal_connect(GTK_OBJECT(file_bt), "clicked",
217                 GTK_SIGNAL_FUNC(print_file_cb), GTK_OBJECT(file_te));
218
219   /* Horizontal box into which to put two vertical boxes of option
220      buttons. */
221   options_hb = gtk_hbox_new(FALSE, 0);
222   gtk_container_border_width(GTK_CONTAINER(options_hb), 5);
223   gtk_container_add(GTK_CONTAINER(main_vb), options_hb);
224   gtk_widget_show(options_hb);
225
226   /* Vertical box into which to put the "Print summary"/"Print detail"
227      radio buttons and the "Print hex" check button. */
228   print_type_vb = gtk_vbox_new(FALSE, 5);
229   gtk_container_border_width(GTK_CONTAINER(print_type_vb), 5);
230   gtk_container_add(GTK_CONTAINER(options_hb), print_type_vb);
231   gtk_widget_show(print_type_vb);
232
233   /* "Print summary"/"Print detail" radio buttons */
234   summary_rb = dlg_radio_button_new_with_label_with_mnemonic(NULL,
235                                 "Print _summary", accel_group);
236   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(summary_rb), FALSE);
237   summary_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(summary_rb));
238   gtk_container_add(GTK_CONTAINER(print_type_vb), summary_rb);
239   gtk_widget_show(summary_rb);
240   detail_rb = dlg_radio_button_new_with_label_with_mnemonic(summary_grp,
241                                 "Print _detail", accel_group);
242   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(detail_rb), TRUE);
243   gtk_signal_connect(GTK_OBJECT(detail_rb), "toggled",
244                         GTK_SIGNAL_FUNC(print_cmd_toggle_detail), NULL);
245   gtk_container_add(GTK_CONTAINER(print_type_vb), detail_rb);
246   gtk_widget_show(detail_rb);
247   
248   /* "Print hex" check button. */
249   hex_cb = dlg_check_button_new_with_label_with_mnemonic("Print _hex data",
250                                 accel_group);
251   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_cb), FALSE);
252   gtk_container_add(GTK_CONTAINER(print_type_vb), hex_cb);
253   gtk_widget_show(hex_cb);
254
255   /* Vertical box into which to put the "Expand all levels"/"Print as displayed"
256      radio buttons. */
257   expand_vb = gtk_vbox_new(FALSE, 5);
258   gtk_container_border_width(GTK_CONTAINER(expand_vb), 5);
259   gtk_container_add(GTK_CONTAINER(options_hb), expand_vb);
260   gtk_widget_show(expand_vb);
261
262   /* "Expand all levels"/"Print as displayed" radio buttons */
263   expand_all_rb = dlg_radio_button_new_with_label_with_mnemonic(NULL,
264                                 "_Expand all levels", accel_group);
265   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(expand_all_rb), TRUE);
266   expand_grp = gtk_radio_button_group(GTK_RADIO_BUTTON(expand_all_rb));
267   gtk_container_add(GTK_CONTAINER(expand_vb), expand_all_rb);
268   gtk_widget_show(expand_all_rb);
269   as_displayed_rb = dlg_radio_button_new_with_label_with_mnemonic(expand_grp,
270                                 "Print _as displayed", accel_group);
271   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(as_displayed_rb), FALSE);
272   gtk_container_add(GTK_CONTAINER(expand_vb), as_displayed_rb);
273   gtk_widget_show(as_displayed_rb);
274
275   gtk_object_set_data(GTK_OBJECT(detail_rb), PRINT_EXPAND_ALL_RB_KEY,
276                         expand_all_rb);
277   gtk_object_set_data(GTK_OBJECT(detail_rb), PRINT_AS_DISPLAYED_RB_KEY,
278                         as_displayed_rb);
279   gtk_object_set_data(GTK_OBJECT(detail_rb), PRINT_HEX_CB_KEY,
280                         hex_cb);
281
282   /* Button row: OK and Cancel buttons */
283   bbox = gtk_hbutton_box_new();
284   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
285   gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
286   gtk_container_add(GTK_CONTAINER(main_vb), bbox);
287   gtk_widget_show(bbox);
288
289   ok_bt = gtk_button_new_with_label ("OK");
290   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_FORMAT_RB_KEY, format_rb);
291   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_DEST_RB_KEY, dest_rb);
292   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_CMD_TE_KEY, cmd_te);
293   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_FILE_TE_KEY, file_te);
294   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_SUMMARY_RB_KEY, summary_rb);
295   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_HEX_CB_KEY, hex_cb);
296   gtk_object_set_data(GTK_OBJECT(ok_bt), PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
297   gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked",
298     GTK_SIGNAL_FUNC(print_ok_cb), GTK_OBJECT(print_w));
299   GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
300   gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
301   gtk_widget_grab_default(ok_bt);
302   gtk_widget_show(ok_bt);
303
304   cancel_bt = gtk_button_new_with_label ("Cancel");
305   gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked",
306     GTK_SIGNAL_FUNC(print_close_cb), GTK_OBJECT(print_w));
307   GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
308   gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
309   gtk_widget_show(cancel_bt);
310
311   /* Catch the "activate" signal on the "Command" and "File" text entries,
312      so that if the user types Return there, we act as if the "OK" button
313      had been selected, as happens if Return is typed if some widget
314      that *doesn't* handle the Return key has the input focus. */
315   dlg_set_activate(cmd_te, ok_bt);
316   dlg_set_activate(file_te, ok_bt);
317
318   /* Catch the "key_press_event" signal in the window, so that we can catch
319      the ESC key being pressed and act as if the "Cancel" button had
320      been selected. */
321   dlg_set_cancel(print_w, cancel_bt);
322
323   gtk_widget_show(print_w);
324 }
325
326 static void
327 print_cmd_toggle_dest(GtkWidget *widget, gpointer data)
328 {
329   GtkWidget     *cmd_lb, *cmd_te, *file_bt, *file_te;
330   int            to_file;
331
332   cmd_lb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
333     PRINT_CMD_LB_KEY));
334   cmd_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
335     PRINT_CMD_TE_KEY));
336   file_bt = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
337     PRINT_FILE_BT_KEY));
338   file_te = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
339     PRINT_FILE_TE_KEY));
340   if (GTK_TOGGLE_BUTTON (widget)->active) {
341     /* They selected "Print to File" */
342     to_file = TRUE;
343   } else {
344     /* They selected "Print to Command" */
345     to_file = FALSE;
346   }
347   gtk_widget_set_sensitive(cmd_lb, !to_file);
348   gtk_widget_set_sensitive(cmd_te, !to_file);
349   gtk_widget_set_sensitive(file_bt, to_file);
350   gtk_widget_set_sensitive(file_te, to_file);
351 }
352
353 static void
354 print_cmd_toggle_detail(GtkWidget *widget, gpointer data)
355 {
356   GtkWidget     *expand_all_rb, *as_displayed_rb, *hex_cb;
357   gboolean      print_detail;
358
359   expand_all_rb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
360     PRINT_EXPAND_ALL_RB_KEY));
361   as_displayed_rb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
362     PRINT_AS_DISPLAYED_RB_KEY));
363   hex_cb = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(widget),
364     PRINT_HEX_CB_KEY));
365   if (GTK_TOGGLE_BUTTON (widget)->active) {
366     /* They selected "Print detail" */
367     print_detail = TRUE;
368   } else {
369     /* They selected "Print summary" */
370     print_detail = FALSE;
371   }
372   gtk_widget_set_sensitive(expand_all_rb, print_detail);
373   gtk_widget_set_sensitive(as_displayed_rb, print_detail);
374   gtk_widget_set_sensitive(hex_cb, print_detail);
375 }
376
377 static void
378 print_file_cb(GtkWidget *file_bt, gpointer file_te)
379 {
380   GtkWidget *caller = gtk_widget_get_toplevel(file_bt);
381   GtkWidget *fs;
382
383   /* Has a file selection dialog box already been opened for that top-level
384      widget? */
385   fs = gtk_object_get_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY);
386
387   if (fs != NULL) {
388     /* Yes.  Just re-activate that dialog box. */
389     reactivate_window(fs);
390     return;
391   }
392
393   fs = gtk_file_selection_new ("Ethereal: Print to File");
394   gtk_object_set_data(GTK_OBJECT(fs), PRINT_FILE_TE_KEY, file_te);
395
396   /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */
397   gtk_object_set_data(GTK_OBJECT(fs), E_FS_CALLER_PTR_KEY, caller);
398
399   /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */
400   gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, fs);
401
402   /* Call a handler when the file selection box is destroyed, so we can inform
403      our caller, if any, that it's been destroyed. */
404   gtk_signal_connect(GTK_OBJECT(fs), "destroy",
405             GTK_SIGNAL_FUNC(print_fs_destroy_cb), NULL);
406
407   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button),
408     "clicked", (GtkSignalFunc) print_fs_ok_cb, fs);
409
410   /* Connect the cancel_button to destroy the widget */
411   gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button),
412     "clicked", (GtkSignalFunc) print_fs_cancel_cb, fs);
413
414   /* Catch the "key_press_event" signal in the window, so that we can catch
415      the ESC key being pressed and act as if the "Cancel" button had
416      been selected. */
417   dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button);
418
419   gtk_widget_show(fs);
420 }
421
422 static void
423 print_fs_ok_cb(GtkWidget *w, gpointer data)
424 {
425   
426   gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data),
427       PRINT_FILE_TE_KEY)),
428       gtk_file_selection_get_filename (GTK_FILE_SELECTION(data)));
429   gtk_widget_destroy(GTK_WIDGET(data));
430 }
431
432 static void
433 print_fs_cancel_cb(GtkWidget *w, gpointer data)
434 {
435   gtk_widget_destroy(GTK_WIDGET(data));
436 }
437
438 static void
439 print_fs_destroy_cb(GtkWidget *win, gpointer data)
440 {
441   GtkWidget *caller;
442
443   /* Get the widget that requested that we be popped up.
444      (It should arrange to destroy us if it's destroyed, so
445      that we don't get a pointer to a non-existent window here.) */
446   caller = gtk_object_get_data(GTK_OBJECT(win), E_FS_CALLER_PTR_KEY);
447
448   /* Tell it we no longer exist. */
449   gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, NULL);
450
451   /* Now nuke this window. */
452   gtk_grab_remove(GTK_WIDGET(win));
453   gtk_widget_destroy(GTK_WIDGET(win));
454 }
455
456 static void
457 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
458 {
459   GtkWidget *button;
460   print_args_t print_args;
461
462   button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
463                                               PRINT_DEST_RB_KEY);
464   print_to_file = GTK_TOGGLE_BUTTON (button)->active;
465   print_args.to_file = print_to_file;
466
467   if (print_args.to_file)
468     print_args.dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
469       PRINT_FILE_TE_KEY))));
470   else
471     print_args.dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(ok_bt),
472       PRINT_CMD_TE_KEY))));
473
474   button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
475                                               PRINT_FORMAT_RB_KEY);
476   if (GTK_TOGGLE_BUTTON (button)->active)
477     print_format = PR_FMT_PS;
478   else
479     print_format = PR_FMT_TEXT;
480   print_args.format = print_format;
481
482   button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
483                                               PRINT_SUMMARY_RB_KEY);
484   print_args.print_summary = GTK_TOGGLE_BUTTON (button)->active;
485
486   button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
487                                               PRINT_HEX_CB_KEY);
488   print_args.print_hex = GTK_TOGGLE_BUTTON (button)->active;
489
490   button = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(ok_bt),
491                                               PRINT_EXPAND_ALL_RB_KEY);
492   print_args.expand_all = GTK_TOGGLE_BUTTON (button)->active;
493
494   gtk_widget_destroy(GTK_WIDGET(parent_w));
495
496   /* Now print the packets */
497   if (!print_packets(&cfile, &print_args)) {
498     if (print_args.to_file)
499       simple_dialog(ESD_TYPE_WARN, NULL,
500         file_write_error_message(errno), print_args.dest);
501     else
502       simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
503         print_args.dest);
504   }
505
506   g_free(print_args.dest);
507 }
508
509 static void
510 print_close_cb(GtkWidget *close_bt, gpointer parent_w)
511 {
512   gtk_grab_remove(GTK_WIDGET(parent_w));
513   gtk_widget_destroy(GTK_WIDGET(parent_w));
514 }
515
516 static void
517 print_destroy_cb(GtkWidget *win, gpointer user_data)
518 {
519   GtkWidget *fs;
520
521   /* Is there a file selection dialog associated with this
522      Print File dialog? */
523   fs = gtk_object_get_data(GTK_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY);
524
525   if (fs != NULL) {
526     /* Yes.  Destroy it. */
527     gtk_widget_destroy(fs);
528   }
529
530   /* Note that we no longer have a "Print" dialog box. */
531   print_w = NULL;
532 }
533
534 /* Print a packet */
535 void
536 file_print_packet_cmd_cb(GtkWidget *widget, gpointer data) {
537   FILE *fh;
538   print_args_t print_args;
539
540   switch (prefs.pr_dest) {
541
542   case PR_DEST_CMD:
543     fh = popen(prefs.pr_cmd, "w");
544     print_args.to_file = FALSE;
545     print_args.dest = prefs.pr_cmd;
546     break;
547
548   case PR_DEST_FILE:
549     fh = fopen(prefs.pr_file, "w");
550     print_args.to_file = TRUE;
551     print_args.dest = prefs.pr_file;
552     break;
553
554   default:
555     fh = NULL;  /* XXX - "can't happen" */
556     break;
557   }
558   if (fh == NULL) {
559     switch (prefs.pr_dest) {
560
561     case PR_DEST_CMD:
562       simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
563         prefs.pr_cmd);
564       break;
565
566     case PR_DEST_FILE:
567       simple_dialog(ESD_TYPE_WARN, NULL, file_write_error_message(errno),
568         prefs.pr_file);
569       break;
570     }
571     return;
572   }
573
574   print_preamble(fh, prefs.pr_format);
575   print_args.format = prefs.pr_format;
576   print_args.print_summary = FALSE;
577   print_args.print_hex = FALSE;
578   print_args.expand_all = TRUE;
579   proto_tree_print(TRUE, &print_args, (GNode*) cfile.protocol_tree, cfile.pd,
580                 cfile.current_frame, fh);
581   print_finale(fh, prefs.pr_format);
582   close_print_dest(print_args.to_file, fh);
583 }