From 88f5e7308328d00b3414f34f4313e1a489df2701 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 29 Jun 2014 15:22:37 -0700 Subject: [PATCH] Make minimum breaks configurable. --- src/output/ascii.c | 12 +++++++++++- src/output/cairo.c | 11 +++++++++++ src/output/options.c | 10 +++++----- src/output/render.c | 4 ++-- src/output/render.h | 7 ++++++- tests/output/render-test.c | 27 ++++++++++++++++++++++++--- 6 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/output/ascii.c b/src/output/ascii.c index 5fe9dc0e6f..201248b448 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, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2007, 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 @@ -164,6 +164,8 @@ struct ascii_driver int top_margin; /* Top margin in lines. */ int bottom_margin; /* Bottom margin in lines. */ + int min_break[TABLE_N_AXES]; /* Min cell size to break across pages. */ + const ucs4_t *box; /* Line & box drawing characters. */ /* Internal state. */ @@ -235,6 +237,7 @@ ascii_create (const char *file_name, enum settings_output_devices device_type, struct string_map *o) { enum { BOX_ASCII, BOX_UNICODE } box; + int min_break[TABLE_N_AXES]; struct output_driver *d; struct ascii_driver *a; int paper_length; @@ -257,11 +260,16 @@ ascii_create (const char *file_name, enum settings_output_devices device_type, 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); + min_break[H] = parse_int (opt (d, o, "min-hbreak", "-1"), -1, INT_MAX); + min_break[V] = parse_int (opt (d, o, "min-vbreak", "-1"), -1, INT_MAX); + a->width = parse_page_size (opt (d, o, "width", "79")); paper_length = parse_page_size (opt (d, o, "length", "66")); a->auto_width = a->width < 0; a->auto_length = paper_length < 0; a->length = paper_length - vertical_margins (a); + a->min_break[H] = min_break[H] >= 0 ? min_break[H] : a->width / 2; + a->min_break[V] = min_break[V] >= 0 ? min_break[V] : a->length / 2; #ifdef HAVE_CAIRO parse_color (d, o, "background-color", "#FFFFFFFFFFFF", &a->bg); parse_color (d, o, "foreground-color", "#000000000000", &a->fg); @@ -444,6 +452,8 @@ ascii_output_table_item (struct ascii_driver *a, params.line_widths[H][i] = width; params.line_widths[V][i] = width; } + for (i = 0; i < TABLE_N_AXES; i++) + params.min_break[i] = a->min_break[i]; if (a->file == NULL && !ascii_open_page (a)) return; diff --git a/src/output/cairo.c b/src/output/cairo.c index e29e6583c5..cbc3afc563 100644 --- a/src/output/cairo.c +++ b/src/output/cairo.c @@ -131,6 +131,8 @@ struct xr_driver int line_space; /* Space between lines. */ int line_width; /* Width of lines. */ + int min_break[TABLE_N_AXES]; /* Min cell size to break across pages. */ + struct xr_color bg; /* Background color */ struct xr_color fg; /* Foreground color */ @@ -253,6 +255,7 @@ apply_options (struct xr_driver *xr, struct string_map *o) int top_margin, bottom_margin; int paper_width, paper_length; int font_size; + int min_break[TABLE_N_AXES]; /* Scale factor from inch/72000 to inch/(72 * XR_POINT). */ const double scale = XR_POINT / 1000.; @@ -290,6 +293,9 @@ apply_options (struct xr_driver *xr, struct string_map *o) top_margin = parse_dimension (opt (d, o, "top-margin", ".5in")); bottom_margin = parse_dimension (opt (d, o, "bottom-margin", ".5in")); + min_break[H] = parse_dimension (opt (d, o, "min-hbreak", NULL)) * scale; + min_break[V] = parse_dimension (opt (d, o, "min-vbreak", NULL)) * scale; + /* Convert to inch/(XR_POINT * 72). */ xr->left_margin = left_margin * scale; xr->right_margin = right_margin * scale; @@ -297,6 +303,8 @@ apply_options (struct xr_driver *xr, struct string_map *o) xr->bottom_margin = bottom_margin * scale; xr->width = (paper_width - left_margin - right_margin) * scale; xr->length = (paper_length - top_margin - bottom_margin) * scale; + xr->min_break[H] = min_break[H] >= 0 ? min_break[H] : xr->width / 2; + xr->min_break[V] = min_break[V] >= 0 ? min_break[V] : xr->length / 2; } static struct xr_driver * @@ -376,6 +384,9 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo) xr->params->line_widths[i][RENDER_LINE_SINGLE] = single_width; xr->params->line_widths[i][RENDER_LINE_DOUBLE] = double_width; } + + for (i = 0; i < TABLE_N_AXES; i++) + xr->params->min_break[i] = xr->min_break[i]; } cairo_set_source_rgb (xr->cairo, xr->fg.red, xr->fg.green, xr->fg.blue); diff --git a/src/output/options.c b/src/output/options.c index b8921255d3..be2bed42d9 100644 --- a/src/output/options.c +++ b/src/output/options.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 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 @@ -48,7 +48,7 @@ driver_option_create (const char *driver_name, const char *name, o->driver_name = xstrdup (driver_name); o->name = xstrdup (name); o->value = value != NULL ? xstrdup (value) : NULL; - o->default_value = xstrdup (default_value); + o->default_value = default_value ? xstrdup (default_value) : NULL; return o; } @@ -261,9 +261,9 @@ parse_dimension (struct driver_option *o) { int retval; - retval = o->value != NULL ? measure_dimension (o->value) : -1; - if (retval == -1) - retval = measure_dimension (o->default_value); + retval = (o->value != NULL ? measure_dimension (o->value) + : o->default_value != NULL ? measure_dimension (o->default_value) + : -1); driver_option_destroy (o); return retval; diff --git a/src/output/render.c b/src/output/render.c index 0ef78f1af6..419affa59f 100644 --- a/src/output/render.c +++ b/src/output/render.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010, 2011, 2013 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 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 @@ -1160,7 +1160,7 @@ cell_is_breakable (const struct render_break *b, int cell) const struct render_page *page = b->page; enum table_axis axis = b->axis; - return cell_width (page, axis, cell) > page->params->size[axis] / 2; + return cell_width (page, axis, cell) >= page->params->min_break[axis]; } /* render_page_select() and helpers. */ diff --git a/src/output/render.h b/src/output/render.h index 51b84a3005..c08a687dc9 100644 --- a/src/output/render.h +++ b/src/output/render.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009, 2010, 2011, 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 @@ -78,6 +78,11 @@ struct render_params /* Width of different kinds of lines. */ int line_widths[TABLE_N_AXES][RENDER_N_LINES]; + + /* Minimum cell width or height before allowing the cell to be broken + across two pages. (Joined cells may always be broken at join + points.) */ + int min_break[TABLE_N_AXES]; }; /* A "page" of content that is ready to be rendered. diff --git a/tests/output/render-test.c b/tests/output/render-test.c index 460f456e45..b996e644cb 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, 2010, 2011, 2012, 2013 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 @@ -99,7 +99,7 @@ main (int argc, char **argv) } static void -configure_drivers (int width, int length) +configure_drivers (int width, int length, int min_break) { struct string_map options, tmp; struct output_driver *driver; @@ -111,6 +111,13 @@ configure_drivers (int width, int length) xasprintf ("%d", width)); string_map_insert_nocopy (&options, xstrdup ("length"), xasprintf ("%d", length)); + if (min_break >= 0) + { + string_map_insert_nocopy (&options, xstrdup ("min-hbreak"), + xasprintf ("%d", min_break)); + string_map_insert_nocopy (&options, xstrdup ("min-vbreak"), + xasprintf ("%d", min_break)); + } if (emphasis != NULL) string_map_insert (&options, "emphasis", emphasis); if (box != NULL) @@ -147,6 +154,13 @@ configure_drivers (int width, int length) 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); @@ -168,12 +182,14 @@ parse_options (int argc, char **argv) { int width = 79; int length = 66; + int min_break = -1; for (;;) { enum { OPT_WIDTH = UCHAR_MAX + 1, OPT_LENGTH, + OPT_MIN_BREAK, OPT_EMPHASIS, OPT_BOX, OPT_HELP @@ -182,6 +198,7 @@ parse_options (int argc, char **argv) { {"width", required_argument, NULL, OPT_WIDTH}, {"length", required_argument, NULL, OPT_LENGTH}, + {"min-break", required_argument, NULL, OPT_MIN_BREAK}, {"transpose", no_argument, &transpose, 1}, {"emphasis", required_argument, NULL, OPT_EMPHASIS}, {"box", required_argument, NULL, OPT_BOX}, @@ -205,6 +222,10 @@ parse_options (int argc, char **argv) length = atoi (optarg); break; + case OPT_MIN_BREAK: + min_break = atoi (optarg); + break; + case OPT_EMPHASIS: emphasis = optarg; break; @@ -229,7 +250,7 @@ parse_options (int argc, char **argv) } - configure_drivers (width, length); + configure_drivers (width, length, min_break); if (optind + 1 != argc) error (1, 0, "exactly one non-option argument required; " -- 2.30.2