X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Foutput%2Fascii.c;h=c9f96b21b58cbd287d2d41152e572ee6a658bd7d;hb=49c02dd0d35698fd43528c4422b3b5202b481a11;hp=14ec71f277d0ae94bef56c9e30247b98ee22bc75;hpb=13d91b755ed1045e2c1183874b3752b07489b922;p=pspp diff --git a/src/output/ascii.c b/src/output/ascii.c index 14ec71f277..c9f96b21b5 100644 --- a/src/output/ascii.c +++ b/src/output/ascii.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2007, 2009 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 2009, 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,25 +22,28 @@ #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "data/file-name.h" +#include "data/settings.h" +#include "libpspp/assertion.h" +#include "libpspp/cast.h" +#include "libpspp/compiler.h" +#include "libpspp/message.h" +#include "libpspp/start-date.h" +#include "libpspp/string-map.h" +#include "libpspp/version.h" +#include "output/cairo.h" +#include "output/chart-item-provider.h" +#include "output/driver-provider.h" +#include "output/message-item.h" #include "output/options.h" -#include -#include -#include -#include -#include +#include "output/render.h" +#include "output/tab.h" +#include "output/table-item.h" +#include "output/text-item.h" -#include "error.h" -#include "minmax.h" -#include "xalloc.h" +#include "gl/error.h" +#include "gl/minmax.h" +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -93,12 +96,11 @@ struct ascii_driver struct output_driver driver; /* User parameters. */ - bool append; /* Append if output-file already exists? */ + bool append; /* Append if output file already exists? */ bool headers; /* Print headers at top of page? */ bool paginate; /* Insert formfeeds? */ bool squeeze_blank_lines; /* Squeeze multiple blank lines into one? */ enum emphasis_style emphasis; /* How to emphasize text. */ - int tab_width; /* Width of a tab; 0 not to use tabs. */ char *chart_file_name; /* Name of files used for charts. */ int width; /* Page width. */ @@ -113,6 +115,7 @@ struct ascii_driver char *init; /* Device initialization string. */ /* Internal state. */ + char *command_name; char *title; char *subtitle; char *file_name; /* Output file name. */ @@ -125,6 +128,10 @@ struct ascii_driver int y; }; +static const struct output_driver_class ascii_driver_class; + +static void ascii_submit (struct output_driver *, const struct output_item *); + static int vertical_margins (const struct ascii_driver *); static const char *get_default_box (int right, int bottom, int left, int top); @@ -147,7 +154,7 @@ static void ascii_draw_cell (void *, const struct table_cell *, static struct ascii_driver * ascii_driver_cast (struct output_driver *driver) { - assert (driver->class == &ascii_class); + assert (driver->class == &ascii_driver_class); return UP_CAST (driver, struct ascii_driver, driver); } @@ -159,7 +166,7 @@ opt (struct output_driver *d, struct string_map *options, const char *key, } static struct output_driver * -ascii_create (const char *name, enum output_device_type device_type, +ascii_create (const char *file_name, enum settings_output_devices device_type, struct string_map *o) { struct output_driver *d; @@ -169,29 +176,21 @@ ascii_create (const char *name, enum output_device_type device_type, a = xzalloc (sizeof *a); d = &a->driver; - output_driver_init (&a->driver, &ascii_class, name, device_type); + output_driver_init (&a->driver, &ascii_driver_class, file_name, device_type); a->append = parse_boolean (opt (d, o, "append", "false")); - a->headers = parse_boolean (opt (d, o, "headers", "true")); - a->paginate = parse_boolean (opt (d, o, "paginate", "true")); - a->squeeze_blank_lines = parse_boolean (opt (d, o, "squeeze", "false")); - a->emphasis = parse_enum (opt (d, o, "emphasis", "bold"), + a->headers = parse_boolean (opt (d, o, "headers", "false")); + a->paginate = parse_boolean (opt (d, o, "paginate", "false")); + a->squeeze_blank_lines = parse_boolean (opt (d, o, "squeeze", "true")); + a->emphasis = parse_enum (opt (d, o, "emphasis", "none"), "bold", EMPH_BOLD, "underline", EMPH_UNDERLINE, "none", EMPH_NONE, - (char *) NULL); - a->tab_width = parse_int (opt (d, o, "tab-width", "0"), 8, INT_MAX); - - if (parse_enum (opt (d, o, "chart-type", "png"), - "png", true, - "none", false, - (char *) NULL)) - a->chart_file_name = parse_chart_file_name (opt (d, o, "chart-files", - "pspp-#.png")); - else - a->chart_file_name = NULL; + NULL_SENTINEL); + + a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", file_name)); - a->top_margin = parse_int (opt (d, o, "top-margin", "2"), 0, INT_MAX); - a->bottom_margin = parse_int (opt (d, o, "bottom-margin", "2"), 0, INT_MAX); + a->top_margin = parse_int (opt (d, o, "top-margin", "0"), 0, INT_MAX); + a->bottom_margin = parse_int (opt (d, o, "bottom-margin", "0"), 0, INT_MAX); a->width = parse_page_size (opt (d, o, "width", "79")); paper_length = parse_page_size (opt (d, o, "length", "66")); @@ -214,9 +213,10 @@ ascii_create (const char *name, enum output_device_type device_type, } a->init = parse_string (opt (d, o, "init", "")); + a->command_name = NULL; a->title = xstrdup (""); a->subtitle = xstrdup (""); - a->file_name = parse_string (opt (d, o, "output-file", "pspp.list")); + a->file_name = xstrdup (file_name); a->file = NULL; a->error = false; a->page_number = 0; @@ -335,6 +335,7 @@ ascii_destroy (struct output_driver *driver) if (a->file != NULL) fn_close (a->file_name, a->file); + free (a->command_name); free (a->title); free (a->subtitle); free (a->file_name); @@ -357,7 +358,7 @@ ascii_flush (struct output_driver *driver) ascii_close_page (a); if (fn_close (a->file_name, a->file) != 0) - error (0, errno, _("ascii: closing output file \"%s\""), + error (0, errno, _("ascii: closing output file `%s'"), a->file_name); a->file = NULL; } @@ -372,103 +373,122 @@ ascii_init_caption_cell (const char *caption, struct table_cell *cell) } static void -ascii_submit (struct output_driver *driver, - const struct output_item *output_item) +ascii_output_table_item (struct ascii_driver *a, + const struct table_item *table_item) { - struct ascii_driver *a = ascii_driver_cast (driver); - if (a->error) - return; - if (is_table_item (output_item)) + const char *caption = table_item_get_caption (table_item); + struct render_params params; + struct render_page *page; + struct render_break x_break; + int caption_height; + int i; + + update_page_size (a, false); + + if (caption != NULL) { - struct table_item *table_item = to_table_item (output_item); - const char *caption = table_item_get_caption (table_item); - struct render_params params; - struct render_page *page; - struct render_break x_break; - int caption_height; - int i; + /* XXX doesn't do well with very large captions */ + struct table_cell cell; + ascii_init_caption_cell (caption, &cell); + caption_height = ascii_measure_cell_height (a, &cell, a->width); + } + else + caption_height = 0; + + params.draw_line = ascii_draw_line; + params.measure_cell_width = ascii_measure_cell_width; + params.measure_cell_height = ascii_measure_cell_height; + params.draw_cell = ascii_draw_cell, + params.aux = a; + params.size[H] = a->width; + params.size[V] = a->length - caption_height; + params.font_size[H] = 1; + params.font_size[V] = 1; + for (i = 0; i < RENDER_N_LINES; i++) + { + int width = i == RENDER_LINE_NONE ? 0 : 1; + params.line_widths[H][i] = width; + params.line_widths[V][i] = width; + } - update_page_size (a, false); + if (a->file == NULL && !ascii_open_page (a)) + return; - if (caption != NULL) - { - /* XXX doesn't do well with very large captions */ - struct table_cell cell; - ascii_init_caption_cell (caption, &cell); - caption_height = ascii_measure_cell_height (a, &cell, a->width); - } - else - caption_height = 0; - - params.draw_line = ascii_draw_line; - params.measure_cell_width = ascii_measure_cell_width; - params.measure_cell_height = ascii_measure_cell_height; - params.draw_cell = ascii_draw_cell, - params.aux = a; - params.size[H] = a->width; - params.size[V] = a->length - caption_height; - params.font_size[H] = 1; - params.font_size[V] = 1; - for (i = 0; i < RENDER_N_LINES; i++) + page = render_page_create (¶ms, table_item_get_table (table_item)); + for (render_break_init (&x_break, page, H); + render_break_has_next (&x_break); ) + { + struct render_page *x_slice; + struct render_break y_break; + + x_slice = render_break_next (&x_break, a->width); + for (render_break_init (&y_break, x_slice, V); + render_break_has_next (&y_break); ) { - int width = i == RENDER_LINE_NONE ? 0 : 1; - params.line_widths[H][i] = width; - params.line_widths[V][i] = width; - } + struct render_page *y_slice; + int space; - if (a->file == NULL && !ascii_open_page (a)) - return; + if (a->y > 0) + a->y++; - page = render_page_create (¶ms, table_item_get_table (table_item)); - for (render_break_init (&x_break, page, H); - render_break_has_next (&x_break); ) - { - struct render_page *x_slice; - struct render_break y_break; + space = a->length - a->y - caption_height; + if (render_break_next_size (&y_break) > space) + { + assert (a->y > 0); + ascii_close_page (a); + if (!ascii_open_page (a)) + return; + continue; + } - x_slice = render_break_next (&x_break, a->width); - for (render_break_init (&y_break, x_slice, V); - render_break_has_next (&y_break); ) + y_slice = render_break_next (&y_break, space); + if (caption_height) { - struct render_page *y_slice; - int space; - - if (a->y > 0) - a->y++; - - space = a->length - a->y - caption_height; - if (render_break_next_size (&y_break) > space) - { - assert (a->y > 0); - ascii_close_page (a); - if (!ascii_open_page (a)) - return; - continue; - } - - y_slice = render_break_next (&y_break, space); - if (caption_height) - { - struct table_cell cell; - int bb[TABLE_N_AXES][2]; - - ascii_init_caption_cell (caption, &cell); - bb[H][0] = 0; - bb[H][1] = a->width; - bb[V][0] = 0; - bb[V][1] = caption_height; - ascii_draw_cell (a, &cell, bb, bb); - a->y += caption_height; - caption_height = 0; - } - render_page_draw (y_slice); - a->y += render_page_get_size (y_slice, V); - render_page_unref (y_slice); + struct table_cell cell; + int bb[TABLE_N_AXES][2]; + + ascii_init_caption_cell (caption, &cell); + bb[H][0] = 0; + bb[H][1] = a->width; + bb[V][0] = 0; + bb[V][1] = caption_height; + ascii_draw_cell (a, &cell, bb, bb); + a->y += caption_height; + caption_height = 0; } - render_break_destroy (&y_break); + render_page_draw (y_slice); + a->y += render_page_get_size (y_slice, V); + render_page_unref (y_slice); } - render_break_destroy (&x_break); + render_break_destroy (&y_break); } + render_break_destroy (&x_break); +} + +static void +ascii_output_text (struct ascii_driver *a, const char *text) +{ + struct table_item *table_item; + + table_item = table_item_create (table_from_string (TAB_LEFT, text), NULL); + ascii_output_table_item (a, table_item); + table_item_unref (table_item); +} + +static void +ascii_submit (struct output_driver *driver, + const struct output_item *output_item) +{ + struct ascii_driver *a = ascii_driver_cast (driver); + + output_driver_track_current_command (output_item, &a->command_name); + + if (a->error) + return; + + if (is_table_item (output_item)) + ascii_output_table_item (a, to_table_item (output_item)); +#ifdef HAVE_CAIRO else if (is_chart_item (output_item) && a->chart_file_name != NULL) { struct chart_item *chart_item = to_chart_item (output_item); @@ -488,6 +508,7 @@ ascii_submit (struct output_driver *driver, free (file_name); } } +#endif /* HAVE_CAIRO */ else if (is_text_item (output_item)) { const struct text_item *text_item = to_text_item (output_item); @@ -520,23 +541,28 @@ ascii_submit (struct output_driver *driver, break; default: - { - struct table_item *item; - - item = table_item_create (table_from_string (TAB_LEFT, text), - NULL); - ascii_submit (&a->driver, &item->output_item); - table_item_unref (item); - } + ascii_output_text (a, text); break; } } + else if (is_message_item (output_item)) + { + const struct message_item *message_item = to_message_item (output_item); + const struct msg *msg = message_item_get_msg (message_item); + char *s = msg_to_string (msg, a->command_name); + ascii_output_text (a, s); + free (s); + } } -const struct output_driver_class ascii_class = +const struct output_driver_factory txt_driver_factory = + { "txt", ascii_create }; +const struct output_driver_factory list_driver_factory = + { "list", ascii_create }; + +static const struct output_driver_class ascii_driver_class = { - "ascii", - ascii_create, + "text", ascii_destroy, ascii_submit, ascii_flush, @@ -778,7 +804,7 @@ ascii_open_page (struct ascii_driver *a) } else { - error (0, errno, _("ascii: opening output file \"%s\""), + error (0, errno, _("ascii: opening output file `%s'"), a->file_name); a->error = true; return false;