2 * Routines for print streams.
4 * Gilbert Ramirez <gram@alumni.rice.edu>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include <epan/print_stream.h>
39 #include <wsutil/file_util.h>
42 open_print_dest(gboolean to_file, const char *dest)
46 /* Open the file or command for output */
48 fh = ws_fopen(dest, "w");
50 fh = popen(dest, "w");
56 close_print_dest(gboolean to_file, FILE *fh)
58 /* Close the file or command */
60 return (fclose(fh) == 0);
62 return (pclose(fh) == 0);
65 /* Some formats need stuff at the beginning of the output */
67 print_preamble(print_stream_t *self, gchar *filename, const char *version_string)
69 return self->ops->print_preamble ? (self->ops->print_preamble)(self, filename, version_string) : TRUE;
73 print_line(print_stream_t *self, int indent, const char *line)
75 return (self->ops->print_line)(self, indent, line);
80 print_bookmark(print_stream_t *self, const gchar *name, const gchar *title)
82 return self->ops->print_bookmark ? (self->ops->print_bookmark)(self, name, title) : TRUE;
86 new_page(print_stream_t *self)
88 return self->ops->new_page ? (self->ops->new_page)(self) : TRUE;
91 /* Some formats need stuff at the end of the output */
93 print_finale(print_stream_t *self)
95 return self->ops->print_finale ? (self->ops->print_finale)(self) : TRUE;
99 destroy_print_stream(print_stream_t *self)
101 return self->ops->destroy ? (self->ops->destroy)(self) : TRUE;
109 #define MAX_INDENT 160
112 print_line_text(print_stream_t *self, int indent, const char *line)
114 static char spaces[MAX_INDENT];
117 output_text *output = (output_text *)self->data;
118 unsigned int num_spaces;
120 /* should be space, if NUL -> initialize */
124 for (i = 0; i < MAX_INDENT; i++)
128 /* Prepare the tabs for printing, depending on tree level */
129 num_spaces = indent * 4;
130 if (num_spaces > MAX_INDENT)
131 num_spaces = MAX_INDENT;
133 ret = fwrite(spaces, 1, num_spaces, output->fh);
134 if (ret == num_spaces) {
135 gchar *tty_out = NULL;
137 if (self->isatty && self->to_codeset) {
138 /* XXX Allocating a fresh buffer every line probably isn't the
139 * most efficient way to do this. However, this has the side
140 * effect of scrubbing invalid output.
142 tty_out = g_convert_with_fallback(line, -1, self->to_codeset, "UTF-8", "?", NULL, NULL, NULL);
147 DWORD out_len = (DWORD) wcslen((wchar_t *) tty_out);
148 WriteConsoleW((HANDLE)_get_osfhandle(_fileno(output->fh)), tty_out, out_len, &out_len, NULL);
150 fputs(tty_out, output->fh);
154 fputs(line, output->fh);
156 putc('\n', output->fh);
158 return !ferror(output->fh);
162 new_page_text(print_stream_t *self)
164 output_text *output = (output_text *)self->data;
166 fputs("\f", output->fh);
167 return !ferror(output->fh);
171 destroy_text(print_stream_t *self)
173 output_text *output = (output_text *)self->data;
176 ret = close_print_dest(output->to_file, output->fh);
182 static const print_stream_ops_t print_text_ops = {
191 static print_stream_t *
192 print_stream_text_alloc(gboolean to_file, FILE *fh)
194 print_stream_t *stream;
197 const gchar *charset;
201 output = (output_text *)g_malloc(sizeof *output);
202 output->to_file = to_file;
204 stream = (print_stream_t *)g_malloc0(sizeof (print_stream_t));
205 stream->ops = &print_text_ops;
206 stream->isatty = ws_isatty(ws_fileno(fh));
207 stream->data = output;
210 /* Is there a more reliable way to do this? */
211 is_utf8 = g_get_charset(&charset);
213 stream->to_codeset = charset;
216 stream->to_codeset = "UTF-16LE";
223 print_stream_text_new(gboolean to_file, const char *dest)
227 fh = open_print_dest(to_file, dest);
231 return print_stream_text_alloc(to_file, fh);
235 print_stream_text_stdio_new(FILE *fh)
237 return print_stream_text_alloc(TRUE, fh);
245 #define MAX_PS_LINE_LENGTH 256
248 void ps_clean_string(char *out, const char *in, int outbuf_size)
258 for (rd = 0, wr = 0 ; wr < outbuf_size; rd++, wr++ ) {
280 print_preamble_ps(print_stream_t *self, gchar *filename, const char *version_string)
282 output_ps *output = (output_ps *)self->data;
283 char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
285 print_ps_preamble(output->fh);
287 fputs("%% the page title\n", output->fh);
288 ps_clean_string(psbuffer, filename, MAX_PS_LINE_LENGTH);
289 fprintf(output->fh, "/ws_pagetitle (%s - Wireshark %s) def\n", psbuffer, version_string);
290 fputs("\n", output->fh);
291 return !ferror(output->fh);
295 print_line_ps(print_stream_t *self, int indent, const char *line)
297 output_ps *output = (output_ps *)self->data;
298 char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
300 ps_clean_string(psbuffer, line, MAX_PS_LINE_LENGTH);
301 fprintf(output->fh, "%d (%s) putline\n", indent, psbuffer);
302 return !ferror(output->fh);
306 print_bookmark_ps(print_stream_t *self, const gchar *name, const gchar *title)
308 output_ps *output = (output_ps *)self->data;
309 char psbuffer[MAX_PS_LINE_LENGTH]; /* static sized buffer! */
312 * See the Adobe "pdfmark reference":
314 * http://partners.adobe.com/asn/acrobat/docs/pdfmark.pdf
316 * The pdfmark stuff tells code that turns PostScript into PDF
317 * things that it should do.
319 * The /OUT stuff creates a bookmark that goes to the
320 * destination with "name" as the name and "title" as the title.
322 * The "/DEST" creates the destination.
324 ps_clean_string(psbuffer, title, MAX_PS_LINE_LENGTH);
325 fprintf(output->fh, "[/Dest /%s /Title (%s) /OUT pdfmark\n", name,
327 fputs("[/View [/XYZ -4 currentpoint matrix currentmatrix matrix defaultmatrix\n",
329 fputs("matrix invertmatrix matrix concatmatrix transform exch pop 20 add null]\n",
331 fprintf(output->fh, "/Dest /%s /DEST pdfmark\n", name);
332 return !ferror(output->fh);
336 new_page_ps(print_stream_t *self)
338 output_ps *output = (output_ps *)self->data;
340 fputs("formfeed\n", output->fh);
341 return !ferror(output->fh);
345 print_finale_ps(print_stream_t *self)
347 output_ps *output = (output_ps *)self->data;
349 print_ps_finale(output->fh);
350 return !ferror(output->fh);
354 destroy_ps(print_stream_t *self)
356 output_ps *output = (output_ps *)self->data;
359 ret = close_print_dest(output->to_file, output->fh);
365 static const print_stream_ops_t print_ps_ops = {
374 static print_stream_t *
375 print_stream_ps_alloc(gboolean to_file, FILE *fh)
377 print_stream_t *stream;
380 output = (output_ps *)g_malloc(sizeof *output);
381 output->to_file = to_file;
383 stream = (print_stream_t *)g_malloc(sizeof (print_stream_t));
384 stream->ops = &print_ps_ops;
385 stream->data = output;
391 print_stream_ps_new(gboolean to_file, const char *dest)
395 fh = open_print_dest(to_file, dest);
399 return print_stream_ps_alloc(to_file, fh);
403 print_stream_ps_stdio_new(FILE *fh)
405 return print_stream_ps_alloc(TRUE, fh);
409 * Editor modelines - http://www.wireshark.org/tools/modelines.html
414 * indent-tabs-mode: nil
417 * vi: set shiftwidth=4 tabstop=8 expandtab:
418 * :indentSize=4:tabSize=8:noTabs=true: