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