Make minimum breaks configurable.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 29 Jun 2014 22:22:37 +0000 (15:22 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 20 Jul 2014 00:44:44 +0000 (17:44 -0700)
src/output/ascii.c
src/output/cairo.c
src/output/options.c
src/output/render.c
src/output/render.h
tests/output/render-test.c

index 5fe9dc0e6f973fa8c5cf89757226a83be2a98072..201248b448effe8c775fbced3cf448b5bc10548c 100644 (file)
@@ -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;
index e29e6583c5f63a74fa9bc6b75d70125d09073098..cbc3afc563f3cfac3185ce300cec2d7b38c3c72d 100644 (file)
@@ -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);
index b8921255d3b08e59b592021b7a025f59f7af1e38..be2bed42d98ecfd8f4040f81e0f912e4b3a3fec6 100644 (file)
@@ -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;
index 0ef78f1af653b27bac865404a255df2aadaaa6eb..419affa59f08b7c015875f729ff20ecad17d0212 100644 (file)
@@ -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];
 }
 \f
 /* render_page_select() and helpers. */
index 51b84a3005cf03705739266c6e68e3d357f8833b..c08a687dc99cba2381cc22f4c319d7277cb616c3 100644 (file)
@@ -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];
   };
 \f
 /* A "page" of content that is ready to be rendered.
index 460f456e45fa4811aad2c915adfa7e36189a85fd..b996e644cb10a7176954cd47cc8f97f8bf30c16a 100644 (file)
@@ -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; "