X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=tests%2Foutput%2Frender-test.c;h=c382ee12c5ef307e51c03deca6fd3cc4f98f5e71;hb=4fc0f7735aa18fc6124a0b663736dcb6d21ea87d;hp=5d8a291816d26911a07418e17660386e0c3392f5;hpb=dfd1972f7bcb550a4fc3b05dbe7e71d12334b0a7;p=pspp diff --git a/tests/output/render-test.c b/tests/output/render-test.c index 5d8a291816..c382ee12c5 100644 --- a/tests/output/render-test.c +++ b/tests/output/render-test.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014 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,31 +22,63 @@ #include #include -#include -#include -#include -#include -#include +#include "data/file-handle-def.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/i18n.h" +#include "libpspp/string-map.h" +#include "output/ascii.h" +#include "output/driver.h" +#include "output/table.h" +#include "output/table-item.h" #include "gl/error.h" #include "gl/progname.h" +#include "gl/xalloc.h" #include "gl/xvasprintf.h" -/* --transpose: Transpose the table before outputting? */ -static int transpose; +/* --emphasis: ASCII driver emphasis option. */ +static bool bold; +static bool underline; + +/* --box: ASCII driver box option. */ +static char *box; + +/* --draw-mode: special ASCII driver test mode. */ +static int draw_mode; + +/* --no-txt: Whether to render to .txt. */ +static int render_txt = true; + +/* --no-stdout: Whether to render to stdout. */ +static int render_stdout = true; + +/* --pdf: Also render PDF output. */ +static int render_pdf; + +/* --csv: Also render CSV output. */ +static int render_csv; + +/* ASCII driver, for ASCII driver test mode. */ +static struct output_driver *ascii_driver; + +/* -o, --output: Base name for output files. */ +static const char *output_base = "render"; static const char *parse_options (int argc, char **argv); static void usage (void) NO_RETURN; static struct table *read_table (FILE *); +static void draw (FILE *); int main (int argc, char **argv) { - struct table *table; const char *input_file_name; FILE *input; set_program_name (argv[0]); + i18n_init (); + output_engine_push (); input_file_name = parse_options (argc, argv); if (!strcmp (input_file_name, "-")) @@ -57,55 +89,184 @@ main (int argc, char **argv) if (input == NULL) error (1, errno, "%s: open failed", input_file_name); } - table = read_table (input); + + if (!draw_mode) + { + struct table **tables = NULL; + size_t allocated_tables = 0; + size_t n_tables = 0; + struct table *table; + + for (;;) + { + int ch; + + if (n_tables >= allocated_tables) + tables = x2nrealloc (tables, &allocated_tables, sizeof *tables); + + tables[n_tables] = read_table (input); + n_tables++; + + ch = getc (input); + if (ch == EOF) + break; + ungetc (ch, input); + } + + table = tables[n_tables - 1]; + table_item_submit (table_item_create (table)); + free (tables); + } + else + draw (input); + if (input != stdin) fclose (input); - if (transpose) - table = table_transpose (table); - - table_item_submit (table_item_create (table, NULL)); - output_close (); + output_engine_pop (); + fh_done (); return 0; } +static void +configure_drivers (int width, int length, int min_break) +{ + struct string_map options, tmp; + struct output_driver *driver; + + string_map_init (&options); + string_map_insert (&options, "format", "txt"); + string_map_insert (&options, "output-file", "-"); + string_map_insert_nocopy (&options, xstrdup ("width"), + xasprintf ("%d", width)); + if (min_break >= 0) + string_map_insert_nocopy (&options, xstrdup ("min-hbreak"), + xasprintf ("%d", min_break)); + if (bold || underline) + string_map_insert (&options, "emphasis", "true"); + if (box != NULL) + string_map_insert (&options, "box", box); + + /* Render to stdout. */ + if (render_stdout) + { + string_map_clone (&tmp, &options); + ascii_driver = driver = output_driver_create (&tmp); + if (driver == NULL) + exit (EXIT_FAILURE); + output_driver_register (driver); + string_map_destroy (&tmp); + } + + if (draw_mode) + { + string_map_destroy (&options); + return; + } + + /* Render to .txt. */ + if (render_txt) + { + string_map_clear (&options); + string_map_insert_nocopy (&options, xstrdup ("output-file"), + xasprintf ("%s.txt", output_base)); + driver = output_driver_create (&options); + if (driver == NULL) + exit (EXIT_FAILURE); + output_driver_register (driver); + } + +#ifdef HAVE_CAIRO + /* Render to .pdf. */ + if (render_pdf) + { + string_map_clear (&options); + string_map_insert_nocopy (&options, xstrdup ("output-file"), + xasprintf ("%s.pdf", output_base)); + string_map_insert (&options, "top-margin", "0"); + string_map_insert (&options, "bottom-margin", "0"); + string_map_insert (&options, "left-margin", "0"); + string_map_insert (&options, "right-margin", "0"); + string_map_insert_nocopy (&options, xstrdup ("paper-size"), + xasprintf ("%dx%dpt", width * 5, length * 8)); + if (min_break >= 0) + { + string_map_insert_nocopy (&options, xstrdup ("min-hbreak"), + xasprintf ("%d", min_break * 5)); + string_map_insert_nocopy (&options, xstrdup ("min-vbreak"), + xasprintf ("%d", min_break * 8)); + } + driver = output_driver_create (&options); + if (driver == NULL) + exit (EXIT_FAILURE); + output_driver_register (driver); + } +#endif + + /* Render to .csv. */ + if (render_csv) + { + string_map_clear (&options); + string_map_insert_nocopy (&options, xstrdup ("output-file"), + xasprintf ("%s.csv", output_base)); + driver = output_driver_create (&options); + if (driver == NULL) + exit (EXIT_FAILURE); + output_driver_register (driver); + } + + /* Render to .odt. */ + string_map_replace_nocopy (&options, xstrdup ("output-file"), + xasprintf ("%s.odt", output_base)); + driver = output_driver_create (&options); + if (driver == NULL) + exit (EXIT_FAILURE); + output_driver_register (driver); + + string_map_destroy (&options); +} + static const char * parse_options (int argc, char **argv) { - bool configured_driver = false; int width = 79; int length = 66; + int min_break = -1; for (;;) { enum { - OPT_DRIVER = UCHAR_MAX + 1, - OPT_WIDTH, + OPT_WIDTH = UCHAR_MAX + 1, OPT_LENGTH, + OPT_MIN_BREAK, + OPT_EMPHASIS, + OPT_BOX, OPT_HELP }; static const struct option options[] = { - {"driver", required_argument, NULL, OPT_DRIVER}, {"width", required_argument, NULL, OPT_WIDTH}, {"length", required_argument, NULL, OPT_LENGTH}, - {"transpose", no_argument, &transpose, 1}, + {"min-break", required_argument, NULL, OPT_MIN_BREAK}, + {"emphasis", required_argument, NULL, OPT_EMPHASIS}, + {"box", required_argument, NULL, OPT_BOX}, + {"draw-mode", no_argument, &draw_mode, 1}, + {"no-txt", no_argument, &render_txt, 0}, + {"no-stdout", no_argument, &render_stdout, 0}, + {"pdf", no_argument, &render_pdf, 1}, + {"csv", no_argument, &render_csv, 1}, + {"output", required_argument, NULL, 'o'}, {"help", no_argument, NULL, OPT_HELP}, {NULL, 0, NULL, 0}, }; - int c = getopt_long (argc, argv, "", options, NULL); + int c = getopt_long (argc, argv, "o:", options, NULL); if (c == -1) break; switch (c) { - case OPT_DRIVER: - output_configure_driver (optarg); - configured_driver = true; - break; - case OPT_WIDTH: width = atoi (optarg); break; @@ -114,6 +275,38 @@ parse_options (int argc, char **argv) length = atoi (optarg); break; + case OPT_MIN_BREAK: + min_break = atoi (optarg); + break; + + case OPT_EMPHASIS: + if (!strcmp (optarg, "bold")) + { + bold = true; + underline = false; + } + else if (!strcmp (optarg, "underline")) + { + bold = false; + underline = true; + } + else if (!strcmp (optarg, "none")) + { + bold = underline = false; + } + else + error (1, 0, "argument to --emphasis must be \"bold\" or " + "\"underline\" or \"none\""); + break; + + case OPT_BOX: + box = optarg; + break; + + case 'o': + output_base = optarg; + break; + case OPT_HELP: usage (); @@ -130,32 +323,7 @@ parse_options (int argc, char **argv) } - if (!configured_driver) - { - char *config; - -#if 1 - config = xasprintf ("ascii:ascii:listing:headers=off top-margin=0 " - "bottom-margin=0 output-file=- emphasis=none " - "paginate=off squeeze=on width=%d length=%d", - width, length); - output_configure_driver (config); - free (config); - - config = xasprintf ("ascii:ascii:listing:headers=off top-margin=0 " - "bottom-margin=0 output-file=render.txt " - "emphasis=none paginate=off squeeze=on"); - output_configure_driver (config); - free (config); -#endif - - config = xasprintf ("pdf:cairo:listing:headers=off top-margin=0 " - "bottom-margin=0 left-margin=0 right-margin=0 " - "output-file=render.pdf paper-size=%dx%dpt", - width * 5, length * 6); - output_configure_driver (config); - free (config); - } + configure_drivers (width, length, min_break); if (optind + 1 != argc) error (1, 0, "exactly one non-option argument required; " @@ -169,7 +337,8 @@ usage (void) printf ("%s, to test rendering of PSPP tables\n" "usage: %s [OPTIONS] INPUT\n" "\nOptions:\n" - " --driver=NAME:CLASS:DEVICE:OPTIONS set output driver\n", + " --width=WIDTH set page width in characters\n" + " --length=LINE set page length in lines\n", program_name, program_name); exit (EXIT_SUCCESS); } @@ -179,7 +348,7 @@ replace_newlines (char *p) { char *q; - for (q = p; *p != '\0'; ) + for (q = p; *p != '\0';) if (*p == '\\' && p[1] == 'n') { *q++ = '\n'; @@ -193,12 +362,13 @@ replace_newlines (char *p) static struct table * read_table (FILE *stream) { - struct tab_table *tab; + struct table *tab; char buffer[1024]; int input[6]; int n_input = 0; int nr, nc, hl, hr, ht, hb; int r, c; + size_t n_footnotes = 0; if (fgets (buffer, sizeof buffer, stream) == NULL || (n_input = sscanf (buffer, "%d %d %d %d %d %d", @@ -213,11 +383,10 @@ read_table (FILE *stream) ht = n_input >= 5 ? input[4] : 0; hb = n_input >= 6 ? input[5] : 0; - tab = tab_create (nc, nr); - tab_headers (tab, hl, hr, ht, hb); + tab = table_create (nc, nr, hl, hr, ht, hb); for (r = 0; r < nr; r++) for (c = 0; c < nc; c++) - if (tab_cell_is_empty (tab, c, r)) + if (table_cell_is_empty (tab, c, r)) { char *new_line; char *text; @@ -244,28 +413,49 @@ read_table (FILE *stream) cs = 1; } - while (*text && strchr ("<>^,@", *text)) +#define S(H) { TABLE_AREA_STYLE_INITIALIZER__, .cell_style.halign = H } + static const struct table_area_style left_style + = S (TABLE_HALIGN_LEFT); + static const struct table_area_style right_style + = S (TABLE_HALIGN_RIGHT); + static const struct table_area_style center_style + = S (TABLE_HALIGN_CENTER); + + const struct table_area_style *style = &right_style; + while (*text && strchr ("<>^,@()|", *text)) switch (*text++) { case '<': - tab_vline (tab, TAL_1, c, r, r + rs - 1); + table_vline (tab, TABLE_STROKE_SOLID, c, r, r + rs - 1); break; case '>': - tab_vline (tab, TAL_1, c + cs, r, r + rs - 1); + table_vline (tab, TABLE_STROKE_SOLID, c + cs, r, r + rs - 1); break; case '^': - tab_hline (tab, TAL_1, c, c + cs - 1, r); + table_hline (tab, TABLE_STROKE_SOLID, c, c + cs - 1, r); break; case ',': - tab_hline (tab, TAL_1, c, c + cs - 1, r + rs); + table_hline (tab, TABLE_STROKE_SOLID, c, c + cs - 1, r + rs); break; case '@': - tab_box (tab, TAL_1, TAL_1, -1, -1, c, r, - c + cs - 1, r + rs - 1); + table_box (tab, TABLE_STROKE_SOLID, TABLE_STROKE_SOLID, + -1, -1, c, r, c + cs - 1, r + rs - 1); + break; + + case '(': + style = &left_style; + break; + + case ')': + style = &right_style; + break; + + case '|': + style = ¢er_style; break; default: @@ -274,11 +464,57 @@ read_table (FILE *stream) replace_newlines (text); - tab_joint_text (tab, c, r, c + cs - 1, r + rs - 1, 0, text); + char *pos = text; + char *content; + int i; + + for (i = 0; (content = strsep (&pos, "#")) != NULL; i++) + if (!i) + { + table_joint_text (tab, c, r, c + cs - 1, r + rs - 1, 0, + content); + table_add_style (tab, c, r, + CONST_CAST (struct table_area_style *, + style)); + } + else + { + char marker[2] = { 'a' + n_footnotes, '\0' }; + struct footnote *f = table_create_footnote ( + tab, n_footnotes, content, marker, + table_area_style_clone (tab->container, &left_style)); + table_add_footnote (tab, c, r, f); + n_footnotes++; + } } - if (getc (stream) != EOF) - error (1, 0, "unread data at end of input"); + return tab; +} + +static void +draw (FILE *stream) +{ + char buffer[1024]; + int line = 0; - return &tab->table; + while (fgets (buffer, sizeof buffer, stream)) + { + char text[sizeof buffer]; + int length; + int emph; + int x, y; + + line++; + if (strchr ("#\r\n", buffer[0])) + continue; + + if (sscanf (buffer, "%d %d %d %[^\n]", &x, &y, &emph, text) == 4) + ascii_test_write (ascii_driver, text, x, y, emph ? bold : false, + emph ? underline : false); + else if (sscanf (buffer, "set-length %d %d", &y, &length) == 2) + ascii_test_set_length (ascii_driver, y, length); + else + error (1, 0, "line %d has invalid format", line); + } + ascii_test_flush (ascii_driver); }