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