print system enhanced, more print ranges and expanded states
[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.49 2003/12/09 22:24:14 ulfl 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 <gtk/gtk.h>
30
31 #include "globals.h"
32 #include "keys.h"
33 #include "print.h"
34 #include "prefs.h"
35 #include "simple_dialog.h"
36 #include "file_dlg.h"
37 #include "ui_util.h"
38 #include "dlg_utils.h"
39 #include "main.h"
40 #include <epan/epan_dissect.h>
41 #include <epan/filesystem.h>
42 #ifdef _WIN32
43 #include <io.h>
44 #include "print_mswin.h"
45 #endif
46 #include "compat_macros.h"
47
48
49 /* On Win32, a GUI application apparently can't use "popen()" (it
50   "returns an invalid file handle, if used in a Windows program,
51   that will cause the program to hang indefinitely"), so we can't
52   use a pipe to a print command to print to a printer.
53
54   Eventually, we should try to use the native Win32 printing API
55   for this (and also use various UNIX printing APIs, when present?).
56 */
57
58 static void print_cmd_toggle_dest(GtkWidget *widget, gpointer data);
59 static void print_cmd_toggle_detail(GtkWidget *widget, gpointer data);
60 static void print_ok_cb(GtkWidget *ok_bt, gpointer parent_w);
61 static void print_close_cb(GtkWidget *close_bt, gpointer parent_w);
62 static void print_destroy_cb(GtkWidget *win, gpointer user_data);
63
64 static gboolean print_prefs_init = FALSE;
65
66 /*
67  * Remember whether we printed to a printer or a file the last time we
68  * printed something.
69  */
70 static int     print_to_file;
71
72 /*
73  * Remember whether we printed as text or PostScript the last time we
74  * printed something.
75  */
76 static gint     print_format;
77
78 static gchar * print_file;
79 static gchar * print_cmd;
80
81 #define PRINT_FORMAT_RB_KEY       "printer_format_radio_button"
82 #define PRINT_DEST_CB_KEY         "printer_destination_check_button"
83
84 #define PRINT_DETAILS_FR_KEY      "printer_details_frame"
85 #define PRINT_DETAILS_CB_KEY      "printer_details_check_button"
86 #define PRINT_HEX_CB_KEY          "printer_hex_check_button"
87 #define PRINT_COLLAPSE_ALL_RB_KEY "printer_collapse_all_radio_button"
88 #define PRINT_AS_DISPLAYED_RB_KEY "printer_as_displayed_radio_button"
89 #define PRINT_EXPAND_ALL_RB_KEY   "printer_expand_all_radio_button"
90
91 #define PRINT_ONLY_SELECTED_RB_KEY    "printer_print_only_selected_radio_button"
92 #define PRINT_ONLY_MARKED_RB_KEY      "printer_print_only_marked_radio_button"
93 #define PRINT_ONLY_DISPLAYED_RB_KEY   "printer_print_only_displayed_radio_button"
94
95 /*
96  * Keep a static pointer to the current "Print" window, if any, so that if
97  * somebody tries to do "File:Print" while there's already a "Print" window
98  * up, we just pop up the existing one, rather than creating a new one.
99  */
100 static GtkWidget *print_w;
101
102 /* Print the capture */
103 void
104 file_print_cmd_cb(GtkWidget *widget _U_, gpointer data _U_)
105 {
106 #if GTK_MAJOR_VERSION < 2
107   GtkAccelGroup *accel_group;
108 #endif
109
110   GtkWidget     *main_vb;
111
112   GtkWidget     *printer_fr, *printer_vb;
113   GtkWidget     *text_rb, *format_rb;
114   GtkWidget     *printer_tb, *dest_cb;
115 #ifndef _WIN32
116   GtkWidget     *cmd_lb, *cmd_te;
117 #endif
118   GtkWidget     *file_bt, *file_te;
119
120   GtkWidget     *range_fr, *range_vb;
121   GtkWidget     *all_captured_rb, *all_displayed_rb, *selected_rb, *marked_rb;
122   GtkWidget     *range_rb;
123
124   GtkWidget     *packet_fr, *packet_vb;
125   GtkWidget     *details_cb, *details_fr, *details_vb;
126   GtkWidget     *collapse_all_rb, *as_displayed_rb, *expand_all_rb,*hex_cb;
127
128   GtkWidget     *bbox, *ok_bt, *cancel_bt;
129
130   GtkTooltips   *tooltips;
131   gchar         label_text[100];
132   frame_data    *packet;
133   guint32       captured_count;
134   guint32       displayed_count;
135
136   if (print_w != NULL) {
137     /* There's already a "Print" dialog box; reactivate it. */
138     reactivate_window(print_w);
139     return;
140   }
141
142   /* count packets */
143   /* XXX: this counters should be a in cfile, so we don't have to do this here */
144   captured_count = 0;
145   displayed_count = 0;
146   packet = cfile.plist;
147   while(packet != NULL) {
148     captured_count++;
149     if (packet->flags.passed_dfilter) {
150       displayed_count++;
151     }
152     packet = packet->next;
153   }
154
155   /* get settings from preferences only once */
156   if(print_prefs_init == FALSE) {
157       print_prefs_init  = TRUE;
158       print_to_file     = prefs.pr_dest;
159       print_format      = prefs.pr_format;
160       print_cmd         = prefs.pr_cmd;
161       print_file        = prefs.pr_file;
162   }
163
164   tooltips = gtk_tooltips_new();
165
166   /* dialog window */
167   print_w = dlg_window_new("Ethereal: Print");
168   SIGNAL_CONNECT(print_w, "destroy", print_destroy_cb, NULL);
169
170 #if GTK_MAJOR_VERSION < 2
171   /* Accelerator group for the accelerators (or, as they're called in
172      Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic,
173      Ctrl+<key> is an accelerator). */
174   accel_group = gtk_accel_group_new();
175   gtk_window_add_accel_group(GTK_WINDOW(print_w), accel_group);
176 #endif
177
178   /* Vertical enclosing container for each row of widgets */
179   main_vb = gtk_vbox_new(FALSE, 5);
180   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
181   gtk_container_add(GTK_CONTAINER(print_w), main_vb);
182   gtk_widget_show(main_vb);
183
184 /*****************************************************/
185
186   /*** printer frame ***/
187   printer_fr = gtk_frame_new("Printer");
188   gtk_box_pack_start(GTK_BOX(main_vb), printer_fr, FALSE, FALSE, 0);
189   gtk_widget_show(printer_fr);
190   printer_vb = gtk_vbox_new(FALSE, 5);
191   gtk_container_border_width(GTK_CONTAINER(printer_vb), 5);
192   gtk_container_add(GTK_CONTAINER(printer_fr), printer_vb);
193   gtk_widget_show(printer_vb);
194
195   /* "Plain text" / "Postscript" radio buttons */
196 #if GTK_MAJOR_VERSION < 2
197   text_rb = dlg_radio_button_new_with_label_with_mnemonic(NULL, "Plain _text",
198                                                          accel_group);
199 #else
200   text_rb = gtk_radio_button_new_with_mnemonic(NULL, "Plain _text");
201 #endif
202   if (print_format == PR_FMT_TEXT)
203     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(text_rb), TRUE);
204   gtk_tooltips_set_tip (tooltips, text_rb, ("Print output in ascii \"plain text\" format"), NULL);
205   gtk_box_pack_start(GTK_BOX(printer_vb), text_rb, FALSE, FALSE, 0);
206   gtk_widget_show(text_rb);
207
208 #if GTK_MAJOR_VERSION < 2
209   format_rb = dlg_radio_button_new_with_label_with_mnemonic(
210                     gtk_radio_button_group(GTK_RADIO_BUTTON(text_rb)),
211                                                             "_PostScript",
212                                                             accel_group);
213 #else
214   format_rb = gtk_radio_button_new_with_mnemonic_from_widget(
215                                 GTK_RADIO_BUTTON(text_rb), "_PostScript");
216 #endif
217   if (print_format == PR_FMT_PS)
218     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(format_rb), TRUE);
219   gtk_tooltips_set_tip (tooltips, format_rb, ("Print output in \"postscript\" format"), NULL);
220   gtk_box_pack_start(GTK_BOX(printer_vb), format_rb, FALSE, FALSE, 0);
221   gtk_widget_show(format_rb);
222
223
224   /* printer table */
225 #ifndef _WIN32
226   printer_tb = gtk_table_new(2, 3, FALSE);
227 #else
228   printer_tb = gtk_table_new(2, 2, FALSE);
229 #endif
230   gtk_box_pack_start(GTK_BOX(printer_vb), printer_tb, FALSE, FALSE, 0);
231   gtk_table_set_row_spacings(GTK_TABLE(printer_tb), 5);
232   gtk_table_set_col_spacings(GTK_TABLE(printer_tb), 5);
233   gtk_widget_show(printer_tb);
234
235
236   /* Output to file button */
237 #if GTK_MAJOR_VERSION < 2
238   dest_cb = dlg_check_button_new_with_label_with_mnemonic("Output to _File:",
239                                                           accel_group);
240 #else
241   dest_cb = gtk_check_button_new_with_mnemonic("Output to _File:");
242 #endif
243   if (print_to_file)
244     gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(dest_cb), TRUE);
245   gtk_tooltips_set_tip (tooltips, dest_cb, ("Output to file instead of printer"), NULL);
246   gtk_table_attach_defaults(GTK_TABLE(printer_tb), dest_cb, 0, 1, 0, 1);
247   gtk_widget_show(dest_cb);
248   
249   /* File text entry and "Browse" button */
250   file_te = gtk_entry_new();
251   OBJECT_SET_DATA(dest_cb, PRINT_FILE_TE_KEY, file_te);
252   gtk_tooltips_set_tip (tooltips, file_te, ("Enter Output filename"), NULL);
253   gtk_entry_set_text(GTK_ENTRY(file_te), print_file);
254   gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_te, 1, 2, 0, 1);
255   gtk_widget_set_sensitive(file_te, print_to_file);
256   gtk_widget_show(file_te);
257   if (print_to_file)
258     gtk_widget_grab_focus(file_te);
259
260   file_bt = gtk_button_new_with_label("Browse");
261   OBJECT_SET_DATA(dest_cb, PRINT_FILE_BT_KEY, file_bt);
262   OBJECT_SET_DATA(file_bt, E_FILE_TE_PTR_KEY, file_te);
263   gtk_tooltips_set_tip (tooltips, file_bt, ("Browse output filename in filesystem"), NULL);
264   gtk_table_attach_defaults(GTK_TABLE(printer_tb), file_bt, 2, 3, 0, 1);
265   gtk_widget_set_sensitive(file_bt, print_to_file);
266   gtk_widget_show(file_bt);
267
268   /* Command label and text entry */
269 #ifndef _WIN32
270   cmd_lb = gtk_label_new("Print command:");
271   OBJECT_SET_DATA(dest_cb, PRINT_CMD_LB_KEY, cmd_lb);
272   gtk_misc_set_alignment(GTK_MISC(cmd_lb), 1.0, 0.5);
273   gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_lb, 0, 1, 1, 2);
274   gtk_widget_set_sensitive(cmd_lb, !print_to_file);
275   gtk_widget_show(cmd_lb);
276
277   cmd_te = gtk_entry_new();
278   OBJECT_SET_DATA(dest_cb, PRINT_CMD_TE_KEY, cmd_te);
279   if (prefs.pr_cmd)
280     gtk_entry_set_text(GTK_ENTRY(cmd_te), prefs.pr_cmd);
281   gtk_tooltips_set_tip (tooltips, cmd_te, ("Enter print command"), NULL);
282   gtk_entry_set_text(GTK_ENTRY(cmd_te), print_cmd);
283   gtk_table_attach_defaults(GTK_TABLE(printer_tb), cmd_te, 1, 2, 1, 2);
284   gtk_widget_set_sensitive(cmd_te, !print_to_file);
285   gtk_widget_show(cmd_te);
286 #endif
287
288   SIGNAL_CONNECT(dest_cb, "toggled", print_cmd_toggle_dest, NULL);
289   SIGNAL_CONNECT(file_bt, "clicked", select_file_cb, "Ethereal: Print to File");
290
291
292 /*****************************************************/
293
294   /*** print range frame ***/
295   range_fr = gtk_frame_new("Print Range");
296   gtk_box_pack_start(GTK_BOX(main_vb), range_fr, FALSE, FALSE, 0);
297   gtk_widget_show(range_fr);
298   range_vb = gtk_vbox_new(FALSE, 5);
299   gtk_container_border_width(GTK_CONTAINER(range_vb), 5);
300   gtk_container_add(GTK_CONTAINER(range_fr), range_vb);
301   gtk_widget_show(range_vb);
302
303
304   /* "Selected packet only" */
305   /* "Marked packets only" */
306   /* "All packets displayed" */
307   /* "All packets captured" */
308   /* "Packets from x to y" */
309
310   g_snprintf(label_text, sizeof(label_text), "_Selected packet only, 1 packet");
311 #if GTK_MAJOR_VERSION < 2
312   selected_rb = dlg_radio_button_new_with_label_with_mnemonic(
313                 NULL,
314                                 label_text, accel_group);
315 #else
316   selected_rb = gtk_radio_button_new_with_mnemonic(
317                     NULL, label_text);
318 #endif
319   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(selected_rb), TRUE);
320   gtk_tooltips_set_tip (tooltips, selected_rb, ("Print the currently selected packet only"), NULL);
321   gtk_container_add(GTK_CONTAINER(range_vb), selected_rb);
322   gtk_widget_show(selected_rb);
323
324   g_snprintf(label_text, sizeof(label_text), "_Marked packets only, %u packet(s)", cfile.marked_count);
325 #if GTK_MAJOR_VERSION < 2
326   marked_rb = dlg_radio_button_new_with_label_with_mnemonic(
327                 gtk_radio_button_group(GTK_RADIO_BUTTON(selected_rb)),
328                                 label_text, accel_group);
329 #else
330   marked_rb = gtk_radio_button_new_with_mnemonic_from_widget(
331                     GTK_RADIO_BUTTON(selected_rb), label_text);
332 #endif
333   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(marked_rb), FALSE);
334   gtk_tooltips_set_tip (tooltips, marked_rb, ("Print marked packets only"), NULL);
335   gtk_container_add(GTK_CONTAINER(range_vb), marked_rb);
336   gtk_widget_set_sensitive(marked_rb, cfile.marked_count);
337   gtk_widget_show(marked_rb);
338
339   g_snprintf(label_text, sizeof(label_text), "All packets _displayed, %u packet(s)", displayed_count);
340 #if GTK_MAJOR_VERSION < 2
341   all_displayed_rb = dlg_radio_button_new_with_label_with_mnemonic(
342                 gtk_radio_button_group(GTK_RADIO_BUTTON(selected_rb)),
343                                 label_text, accel_group);
344 #else
345   all_displayed_rb = gtk_radio_button_new_with_mnemonic_from_widget(
346                     GTK_RADIO_BUTTON(selected_rb), label_text);
347 #endif
348   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(all_displayed_rb), FALSE);
349   gtk_tooltips_set_tip (tooltips, all_displayed_rb, 
350       ("Print all packets currently displayed"), NULL);
351   gtk_container_add(GTK_CONTAINER(range_vb), all_displayed_rb);
352   gtk_widget_set_sensitive(all_displayed_rb, displayed_count != captured_count);
353   gtk_widget_show(all_displayed_rb);
354
355   g_snprintf(label_text, sizeof(label_text), "All packets _captured, %u packet(s)", captured_count);
356 #if GTK_MAJOR_VERSION < 2
357   all_captured_rb = dlg_radio_button_new_with_label_with_mnemonic(
358                 gtk_radio_button_group(GTK_RADIO_BUTTON(selected_rb)),
359                                 label_text, accel_group);
360 #else
361   all_captured_rb = gtk_radio_button_new_with_mnemonic_from_widget(
362                     GTK_RADIO_BUTTON(selected_rb), label_text);
363 #endif
364   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(all_captured_rb), FALSE);
365   gtk_tooltips_set_tip (tooltips, all_captured_rb, 
366       ("Print all packets captured"), NULL);
367   gtk_container_add(GTK_CONTAINER(range_vb), all_captured_rb);
368   gtk_widget_show(all_captured_rb);
369
370 #if GTK_MAJOR_VERSION < 2
371   range_rb = dlg_radio_button_new_with_label_with_mnemonic(
372                 gtk_radio_button_group(GTK_RADIO_BUTTON(selected_rb)),
373                                 "XXX: Packets f_rom X to Y", accel_group);
374 #else
375   range_rb = gtk_radio_button_new_with_mnemonic_from_widget(
376                     GTK_RADIO_BUTTON(selected_rb), "XXX: Packets f_rom X to Y");
377 #endif
378   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(range_rb), FALSE);
379   gtk_tooltips_set_tip (tooltips, range_rb, ("Print packets from number X to Y only"), NULL);
380   gtk_container_add(GTK_CONTAINER(range_vb), range_rb);
381   /*gtk_widget_show(range_rb);*/
382
383
384 /*****************************************************/
385
386   /*** packet format frame ***/
387   packet_fr = gtk_frame_new("Packet Format");
388   gtk_box_pack_start(GTK_BOX(main_vb), packet_fr, FALSE, FALSE, 0);
389   gtk_widget_show(packet_fr);
390   packet_vb = gtk_vbox_new(FALSE, 5);
391   gtk_container_border_width(GTK_CONTAINER(packet_vb), 5);
392   gtk_container_add(GTK_CONTAINER(packet_fr), packet_vb);
393   gtk_widget_show(packet_vb);
394
395   /* "Print detail" check buttons */
396 #if GTK_MAJOR_VERSION < 2
397   details_cb = dlg_check_button_new_with_label_with_mnemonic("Print packet d_etails", 
398                                                             accel_group);
399 #else
400   details_cb = gtk_check_button_new_with_mnemonic("Print packet d_etails");
401 #endif
402   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(details_cb), TRUE);
403   SIGNAL_CONNECT(details_cb, "clicked", print_cmd_toggle_detail, NULL);
404   gtk_tooltips_set_tip (tooltips, details_cb, ("Print packet details, or packet summary only"), NULL);
405   gtk_container_add(GTK_CONTAINER(packet_vb), details_cb);
406   gtk_widget_show(details_cb);
407
408
409   /*** (inner) details frame ***/
410   details_fr = gtk_frame_new("Details");
411   gtk_box_pack_start(GTK_BOX(packet_vb), details_fr, FALSE, FALSE, 0);
412   gtk_widget_show(details_fr);
413
414   details_vb = gtk_vbox_new(FALSE, 5);
415   gtk_container_border_width(GTK_CONTAINER(details_vb), 5);
416   gtk_container_add(GTK_CONTAINER(details_fr), details_vb);
417   gtk_widget_show(details_vb);
418
419   /* "All collapsed"/"As displayed"/"All Expanded" radio buttons */
420 #if GTK_MAJOR_VERSION < 2
421   collapse_all_rb = dlg_radio_button_new_with_label_with_mnemonic(NULL,
422                                     "All dissections co_llapsed", accel_group);
423 #else
424   collapse_all_rb = gtk_radio_button_new_with_mnemonic(
425                     NULL, "All dissections co_llapsed");
426 #endif
427   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(collapse_all_rb), FALSE);
428   gtk_tooltips_set_tip (tooltips, collapse_all_rb, ("Print packet details tree \"collapsed\""), NULL);
429   gtk_container_add(GTK_CONTAINER(details_vb), collapse_all_rb);
430   gtk_widget_show(collapse_all_rb);
431
432 #if GTK_MAJOR_VERSION < 2
433   as_displayed_rb = dlg_radio_button_new_with_label_with_mnemonic(
434                     gtk_radio_button_group(GTK_RADIO_BUTTON(collapse_all_rb)),
435                                     "Dissections as displa_yed", accel_group);
436 #else
437   as_displayed_rb = gtk_radio_button_new_with_mnemonic_from_widget(
438                     GTK_RADIO_BUTTON(collapse_all_rb), "Dissections as displa_yed");
439 #endif
440   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(as_displayed_rb), TRUE);
441   gtk_tooltips_set_tip (tooltips, as_displayed_rb, ("Print packet details tree \"as displayed\""), NULL);
442   gtk_container_add(GTK_CONTAINER(details_vb), as_displayed_rb);
443   gtk_widget_show(as_displayed_rb);
444
445 #if GTK_MAJOR_VERSION < 2
446   expand_all_rb = dlg_radio_button_new_with_label_with_mnemonic(
447                     gtk_radio_button_group(GTK_RADIO_BUTTON(collapse_all_rb)),
448                                     "All dissections e_xpanded", accel_group);
449 #else
450   expand_all_rb = gtk_radio_button_new_with_mnemonic_from_widget(
451                     GTK_RADIO_BUTTON(collapse_all_rb), "All dissections e_xpanded");
452 #endif
453   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(expand_all_rb), FALSE);
454   gtk_tooltips_set_tip (tooltips, expand_all_rb, ("Print packet details tree \"expanded\""), NULL);
455   gtk_container_add(GTK_CONTAINER(details_vb), expand_all_rb);
456   gtk_widget_show(expand_all_rb);
457
458   /* "Print hex" check button. */
459 #if GTK_MAJOR_VERSION < 2
460   hex_cb = dlg_check_button_new_with_label_with_mnemonic("Packet _hex data",
461                                                          accel_group);
462 #else
463   hex_cb = gtk_check_button_new_with_mnemonic("Packet _hex data");
464 #endif
465   gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(hex_cb), FALSE);
466   gtk_tooltips_set_tip (tooltips, hex_cb, ("Add hexdump of packet data"), NULL);
467   gtk_container_add(GTK_CONTAINER(details_vb), hex_cb);
468   gtk_widget_show(hex_cb);
469
470
471   OBJECT_SET_DATA(details_cb, PRINT_DETAILS_FR_KEY, details_fr);
472   OBJECT_SET_DATA(details_cb, PRINT_COLLAPSE_ALL_RB_KEY, collapse_all_rb);
473   OBJECT_SET_DATA(details_cb, PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
474   OBJECT_SET_DATA(details_cb, PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
475   OBJECT_SET_DATA(details_cb, PRINT_HEX_CB_KEY, hex_cb);
476
477 /*****************************************************/
478
479
480   /* Button row: OK and Cancel buttons */
481   bbox = gtk_hbutton_box_new();
482   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
483   gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
484   gtk_container_add(GTK_CONTAINER(main_vb), bbox);
485   gtk_widget_show(bbox);
486
487 #if GTK_MAJOR_VERSION < 2
488   ok_bt = gtk_button_new_with_label ("OK");
489 #else
490   ok_bt = gtk_button_new_from_stock(GTK_STOCK_OK);
491 #endif
492   OBJECT_SET_DATA(ok_bt, PRINT_FORMAT_RB_KEY, format_rb);
493   OBJECT_SET_DATA(ok_bt, PRINT_DEST_CB_KEY, dest_cb);
494 #ifndef _WIN32
495   OBJECT_SET_DATA(ok_bt, PRINT_CMD_TE_KEY, cmd_te);
496 #endif
497
498   OBJECT_SET_DATA(ok_bt, PRINT_FILE_TE_KEY, file_te);
499   OBJECT_SET_DATA(ok_bt, PRINT_DETAILS_CB_KEY, details_cb);
500   OBJECT_SET_DATA(ok_bt, PRINT_HEX_CB_KEY, hex_cb);
501   OBJECT_SET_DATA(ok_bt, PRINT_AS_DISPLAYED_RB_KEY, as_displayed_rb);
502   OBJECT_SET_DATA(ok_bt, PRINT_EXPAND_ALL_RB_KEY, expand_all_rb);
503   OBJECT_SET_DATA(ok_bt, PRINT_ONLY_SELECTED_RB_KEY, selected_rb);
504   OBJECT_SET_DATA(ok_bt, PRINT_ONLY_MARKED_RB_KEY, marked_rb);
505   OBJECT_SET_DATA(ok_bt, PRINT_ONLY_DISPLAYED_RB_KEY, all_displayed_rb);
506   SIGNAL_CONNECT(ok_bt, "clicked", print_ok_cb, print_w);
507   GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT);
508   gtk_tooltips_set_tip (tooltips, ok_bt, ("Perform printing"), NULL);
509   gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0);
510   gtk_widget_grab_default(ok_bt);
511   gtk_widget_show(ok_bt);
512
513 #if GTK_MAJOR_VERSION < 2
514   cancel_bt = gtk_button_new_with_label ("Cancel");
515 #else
516   cancel_bt = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
517 #endif
518   SIGNAL_CONNECT(cancel_bt, "clicked", print_close_cb, print_w);
519   GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT);
520   gtk_tooltips_set_tip (tooltips, cancel_bt, ("Cancel print and exit"), NULL);
521   gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0);
522   gtk_widget_show(cancel_bt);
523
524   /* Catch the "activate" signal on the "Command" and "File" text entries,
525      so that if the user types Return there, we act as if the "OK" button
526      had been selected, as happens if Return is typed if some widget
527      that *doesn't* handle the Return key has the input focus. */
528
529 #ifndef _WIN32
530   dlg_set_activate(cmd_te, ok_bt);
531 #endif
532   dlg_set_activate(file_te, ok_bt);
533
534   /* Catch the "key_press_event" signal in the window, so that we can catch
535      the ESC key being pressed and act as if the "Cancel" button had
536      been selected. */
537   dlg_set_cancel(print_w, cancel_bt);
538
539   gtk_widget_show(print_w);
540 }
541
542 static void
543 print_cmd_toggle_dest(GtkWidget *widget, gpointer data _U_)
544 {
545 #ifndef _WIN32
546   GtkWidget     *cmd_lb, *cmd_te;
547 #endif
548   GtkWidget     *file_bt, *file_te;
549   int            to_file;
550
551 #ifndef _WIN32
552   cmd_lb = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_CMD_LB_KEY));
553   cmd_te = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_CMD_TE_KEY));
554 #endif
555   file_bt = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_FILE_BT_KEY));
556   file_te = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_FILE_TE_KEY));
557   if (GTK_TOGGLE_BUTTON (widget)->active) {
558     /* They selected "Print to File" */
559     to_file = TRUE;
560   } else {
561     /* They selected "Print to Command" on UNIX or "Print to Printer"
562        on Windows */
563     to_file = FALSE;
564   }
565 #ifndef _WIN32
566   gtk_widget_set_sensitive(cmd_lb, !to_file);
567   gtk_widget_set_sensitive(cmd_te, !to_file);
568 #endif
569   gtk_widget_set_sensitive(file_bt, to_file);
570   gtk_widget_set_sensitive(file_te, to_file);
571 }
572
573 static void
574 print_cmd_toggle_detail(GtkWidget *widget, gpointer data _U_)
575 {
576   GtkWidget     *collapse_all_rb, *expand_all_rb, *as_displayed_rb, *hex_cb, *details_fr;
577   gboolean      print_detail;
578
579   details_fr = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_DETAILS_FR_KEY));
580   collapse_all_rb = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_COLLAPSE_ALL_RB_KEY));
581   as_displayed_rb = GTK_WIDGET(OBJECT_GET_DATA(widget,
582                                                PRINT_AS_DISPLAYED_RB_KEY));
583   expand_all_rb = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_EXPAND_ALL_RB_KEY));
584   hex_cb = GTK_WIDGET(OBJECT_GET_DATA(widget, PRINT_HEX_CB_KEY));
585
586   if (GTK_TOGGLE_BUTTON (widget)->active) {
587     /* They selected "Print detail" */
588     print_detail = TRUE;
589   } else {
590     /* They selected "Print summary" */
591     print_detail = FALSE;
592   }
593
594   gtk_widget_set_sensitive(details_fr, print_detail);
595   gtk_widget_set_sensitive(collapse_all_rb, print_detail);
596   gtk_widget_set_sensitive(as_displayed_rb, print_detail);
597   gtk_widget_set_sensitive(expand_all_rb, print_detail);
598   gtk_widget_set_sensitive(hex_cb, print_detail);
599 }
600
601 #ifdef _WIN32
602
603 void setup_mswin_print( print_args_t *print_args) {
604
605 /*XXX should use temp file stuff in util routines */
606
607     char *path1;
608
609     path1 = tmpnam(NULL);
610
611     print_args->dest = g_strdup(path1);
612     print_args->to_file = TRUE;
613 }
614 #endif
615
616 static void
617 print_ok_cb(GtkWidget *ok_bt, gpointer parent_w)
618 {
619   GtkWidget     *button;
620   print_args_t  print_args;
621   const gchar   *g_dest;
622   gchar         *f_name;
623   gchar         *dirname;
624 #ifdef _WIN32
625   int win_printer_flag = FALSE;
626 #endif
627
628   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DEST_CB_KEY);
629   print_to_file = GTK_TOGGLE_BUTTON (button)->active;
630   print_args.to_file = print_to_file;
631
632   if (print_args.to_file) {
633     g_dest = gtk_entry_get_text(GTK_ENTRY(OBJECT_GET_DATA(ok_bt,
634                                                           PRINT_FILE_TE_KEY)));
635     if (!g_dest[0]) {
636       simple_dialog(ESD_TYPE_CRIT, NULL,
637         "Printing to file, but no file specified.");
638       return;
639     }
640     print_args.dest = g_strdup(g_dest);
641     /* Save the directory name for future file dialogs. */
642     f_name = g_strdup(g_dest);
643     dirname = get_dirname(f_name);  /* Overwrites f_name */
644     set_last_open_dir(dirname);
645     g_free(f_name);
646   } else {
647 #ifdef _WIN32
648     win_printer_flag = TRUE;
649     setup_mswin_print(&print_args);
650 #else
651     print_args.dest = g_strdup(gtk_entry_get_text(GTK_ENTRY(OBJECT_GET_DATA(ok_bt,
652       PRINT_CMD_TE_KEY))));
653 #endif
654   }
655
656   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_FORMAT_RB_KEY);
657   if (GTK_TOGGLE_BUTTON (button)->active)
658     print_format = PR_FMT_PS;
659   else
660     print_format = PR_FMT_TEXT;
661   print_args.format = print_format;
662
663   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_DETAILS_CB_KEY);
664   print_args.print_summary = !(GTK_TOGGLE_BUTTON (button)->active);
665
666   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_HEX_CB_KEY);
667   print_args.print_hex = GTK_TOGGLE_BUTTON (button)->active;
668
669   print_args.print_dissections = print_dissections_collapsed;
670
671   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_AS_DISPLAYED_RB_KEY);
672   if (GTK_TOGGLE_BUTTON (button)->active) {
673     print_args.print_dissections = print_dissections_as_displayed;
674   }
675   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_EXPAND_ALL_RB_KEY);
676   if (GTK_TOGGLE_BUTTON (button)->active) {
677     print_args.print_dissections = print_dissections_expanded;
678   }
679
680   print_args.print_range = print_range_all_captured;
681
682   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_ONLY_SELECTED_RB_KEY);
683   if (GTK_TOGGLE_BUTTON (button)->active) {
684     print_args.print_range = print_range_selected_only;
685   }
686   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_ONLY_MARKED_RB_KEY);
687   if (GTK_TOGGLE_BUTTON (button)->active) {
688     print_args.print_range = print_range_marked_only;
689   }
690   button = (GtkWidget *)OBJECT_GET_DATA(ok_bt, PRINT_ONLY_DISPLAYED_RB_KEY);
691   if (GTK_TOGGLE_BUTTON (button)->active) {
692     print_args.print_range = print_range_all_displayed;
693   }
694
695   gtk_widget_destroy(GTK_WIDGET(parent_w));
696
697   /* Now print the packets */
698   if (!print_packets(&cfile, &print_args)) {
699     if (print_args.to_file)
700       simple_dialog(ESD_TYPE_WARN, NULL,
701         file_write_error_message(errno), print_args.dest);
702     else
703       simple_dialog(ESD_TYPE_WARN, NULL, "Couldn't run print command %s.",
704         print_args.dest);
705   }
706
707 #ifdef _WIN32
708   if (win_printer_flag) {
709     print_mswin(print_args.dest);
710
711     /* trash temp file */
712     remove(print_args.dest);
713   }
714 #endif
715
716   g_free(print_args.dest);
717 }
718
719 static void
720 print_close_cb(GtkWidget *close_bt _U_, gpointer parent_w)
721 {
722   gtk_grab_remove(GTK_WIDGET(parent_w));
723   gtk_widget_destroy(GTK_WIDGET(parent_w));
724 }
725
726 static void
727 print_destroy_cb(GtkWidget *win, gpointer user_data _U_)
728 {
729   GtkWidget *fs;
730
731   /* Is there a file selection dialog associated with this
732      Print File dialog? */
733   fs = OBJECT_GET_DATA(win, E_FILE_SEL_DIALOG_PTR_KEY);
734
735   if (fs != NULL) {
736     /* Yes.  Destroy it. */
737     gtk_widget_destroy(fs);
738   }
739
740   /* Note that we no longer have a "Print" dialog box. */
741   print_w = NULL;
742 }
743
744
745
746