render: Fix rendering corner cases when a cell is broken across pages.
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 20 Jul 2014 00:44:30 +0000 (17:44 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 20 Jul 2014 00:44:45 +0000 (17:44 -0700)
The rendering code ability to break individual cells across multiple pages
has never received good test coverage because the criteria for doing that
are strict enough that the testsuite hardly ever does it.  This commit adds
a "--min-break=0" version to each test in the testsuite, which uncovers a
number of bugs in the cell breaking code.  It also fixes those bugs.

src/output/render.c
tests/output/render.at

index 419affa59f08b7c015875f729ff20ecad17d0212..8529603be640d98e5336ecbc5aca7109cdc38a18 100644 (file)
@@ -178,6 +178,21 @@ cell_width (const struct render_page *page, int axis, int x)
   return axis_width (page, axis, cell_ofs (x), cell_ofs (x) + 1);
 }
 
+/* Returns the width of rule X along AXIS in PAGE. */
+static int
+rule_width (const struct render_page *page, int axis, int x)
+{
+  return axis_width (page, axis, rule_ofs (x), rule_ofs (x) + 1);
+}
+
+/* Returns the width of rule X along AXIS in PAGE. */
+static int
+rule_width_r (const struct render_page *page, int axis, int x)
+{
+  int ofs = rule_ofs_r (page, axis, x);
+  return axis_width (page, axis, ofs, ofs + 1);
+}
+
 /* Returns the width of cells X0 through X1, exclusive, along AXIS in PAGE. */
 static int
 joined_width (const struct render_page *page, int axis, int x0, int x1)
@@ -899,13 +914,13 @@ render_cell (const struct render_page *page, const struct table_cell *cell)
           if (of->overflow[axis][0])
             {
               bb[axis][0] -= of->overflow[axis][0];
-              if (cell->d[axis][0] == 0)
+              if (cell->d[axis][0] == 0 && !page->is_edge_cutoff[axis][0])
                 clip[axis][0] = page->cp[axis][cell->d[axis][0] * 2];
             }
           if (of->overflow[axis][1])
             {
               bb[axis][1] += of->overflow[axis][1];
-              if (cell->d[axis][1] == page->n[axis])
+              if (cell->d[axis][1] == page->n[axis] && !page->is_edge_cutoff[axis][1])
                 clip[axis][1] = page->cp[axis][cell->d[axis][1] * 2 + 1];
             }
         }
@@ -1111,19 +1126,57 @@ render_break_next (struct render_break *b, int size)
 
   pixel = 0;
   for (cell = b->cell; cell < page->n[axis] - page->h[axis][1]; cell++)
-    if (needed_size (b, cell + 1) > size)
-      {
-        if (!cell_is_breakable (b, cell))
-          {
-            if (cell == b->cell)
-              return NULL;
-          }
-        else
-          pixel = (cell == b->cell
-                   ? b->pixel + size - b->hw
-                   : size - needed_size (b, cell));
-        break;
-      }
+    {
+      int needed = needed_size (b, cell + 1);
+      if (needed > size)
+        {
+          if (cell_is_breakable (b, cell))
+            {
+              /* If there is no right header and we render a partial cell on
+                 the right side of the body, then we omit the rightmost rule of
+                 the body.  Otherwise the rendering is deceptive because it
+                 looks like the whole cell is present instead of a partial
+                 cell.
+
+                 This is similar to code for the left side in needed_size(). */
+              int rule_allowance = (page->h[axis][1]
+                                    ? 0
+                                    : rule_width (page, axis, cell));
+
+              /* The amount that, if we added 'cell', the rendering would
+                 overfill the allocated 'size'. */
+              int overhang = needed - size - rule_allowance;
+
+              /* The width of 'cell'. */
+              int cell_size = cell_width (page, axis, cell);
+
+              /* The amount trimmed the left side of 'cell',
+                 and the amount left to render. */
+              int cell_ofs = cell == b->cell ? b->pixel : 0;
+              int cell_left = cell_size - cell_ofs;
+
+              /* A small but visible width.  */
+              int em = page->params->font_size[axis];
+
+              /* If some of the cell remains to render,
+                 and there would still be some of the cell left afterward,
+                 then partially render that much of the cell. */
+              pixel = (cell_left && cell_left > overhang
+                       ? cell_left - overhang + cell_ofs
+                       : 0);
+
+              /* If there would be only a tiny amount of the cell left after
+                 rendering it partially, reduce the amount rendered slightly
+                 to make the output look a little better. */
+              if (pixel + em > cell_size)
+                pixel = MAX (pixel - em, 0);
+            }
+          break;
+        }
+    }
+
+  if (cell == b->cell && !pixel)
+    return NULL;
 
   subpage = render_page_select (page, axis, b->cell, b->pixel,
                                 pixel ? cell + 1 : cell,
@@ -1143,7 +1196,33 @@ needed_size (const struct render_break *b, int cell)
   enum table_axis axis = b->axis;
   int size;
 
-  size = joined_width (page, axis, b->cell, cell) + b->hw - b->pixel;
+  /* Width of left header not including its rightmost rule.  */
+  size = axis_width (page, axis, 0, rule_ofs (page->h[axis][0]));
+
+  /* If we have a pixel offset and there is no left header, then we omit the
+     leftmost rule of the body.  Otherwise the rendering is deceptive because
+     it looks like the whole cell is present instead of a partial cell.
+
+     Otherwise (if there are headers) we will be merging two rules: the
+     rightmost rule in the header and the leftmost rule in the body.  We assume
+     that the width of a merged rule is the larger of the widths of either rule
+     invidiually. */
+  if (b->pixel == 0 || page->h[axis][0])
+    size += MAX (rule_width (page, axis, page->h[axis][0]),
+                 rule_width (page, axis, b->cell));
+
+  /* Width of body, minus any pixel offset in the leftmost cell. */
+  size += joined_width (page, axis, b->cell, cell) - b->pixel;
+
+  /* Width of rightmost rule in body merged with leftmost rule in headers. */
+  size += MAX (rule_width_r (page, axis, page->h[axis][1]),
+               rule_width (page, axis, cell));
+
+  /* Width of right header not including its leftmost rule. */
+  size += axis_width (page, axis, rule_ofs_r (page, axis, page->h[axis][1]),
+                      rule_ofs_r (page, axis, 0));
+
+  /* Join crossing. */
   if (page->h[axis][0] && page->h[axis][1])
     size += page->join_crossing[axis][b->cell];
 
@@ -1257,7 +1336,12 @@ render_page_select (const struct render_page *page, enum table_axis axis,
   dcp = subpage->cp[a];
   *dcp = 0;
   for (z = 0; z <= rule_ofs (subpage->h[a][0]); z++, dcp++)
-    dcp[1] = dcp[0] + (scp[z + 1] - scp[z]);
+    {
+      if (z == 0 && subpage->is_edge_cutoff[a][0])
+        dcp[1] = dcp[0];
+      else
+        dcp[1] = dcp[0] + (scp[z + 1] - scp[z]);
+    }
   for (z = cell_ofs (z0); z <= cell_ofs (z1 - 1); z++, dcp++)
     {
       dcp[1] = dcp[0] + (scp[z + 1] - scp[z]);
@@ -1272,7 +1356,12 @@ render_page_select (const struct render_page *page, enum table_axis axis,
     }
   for (z = rule_ofs_r (page, a, subpage->h[a][1]);
        z <= rule_ofs_r (page, a, 0); z++, dcp++)
-    dcp[1] = dcp[0] + (scp[z + 1] - scp[z]);
+    {
+      if (z == rule_ofs_r (page, a, 0) && subpage->is_edge_cutoff[a][1])
+        dcp[1] = dcp[0];
+      else
+        dcp[1] = dcp[0] + (scp[z + 1] - scp[z]);
+    }
   assert (dcp == &subpage->cp[a][2 * subpage->n[a] + 1]);
 
   for (z = 0; z < page->n[b] * 2 + 2; z++)
@@ -1289,49 +1378,61 @@ render_page_select (const struct render_page *page, enum table_axis axis,
   s.subpage = subpage;
 
   if (!page->h[a][0] || z0 > page->h[a][0] || p0)
-    for (z = 0; z < page->n[b]; z++)
+    for (z = 0; z < page->n[b]; )
       {
         struct table_cell cell;
         int d[TABLE_N_AXES];
+        bool overflow0;
+        bool overflow1;
 
         d[a] = z0;
         d[b] = z;
+
         table_get_cell (page->table, d[H], d[V], &cell);
-        if ((z == cell.d[b][0] && (p0 || cell.d[a][0] < z0))
-            || (z == cell.d[b][1] - 1 && p1))
+        overflow0 = p0 || cell.d[a][0] < z0;
+        overflow1 = cell.d[a][1] > z1 || (cell.d[a][1] == z1 && p1);
+        if (overflow0 || overflow1)
           {
             ro = insert_overflow (&s, &cell);
-            ro->overflow[a][0] += p0 + axis_width (page, a,
-                                                   cell_ofs (cell.d[a][0]),
-                                                   cell_ofs (z0));
-            if (z1 == z0 + 1)
-              ro->overflow[a][1] += p1;
-            if (page->h[a][0] && page->h[a][1])
-              ro->overflow[a][0] -= page->join_crossing[a][cell.d[a][0] + 1];
-            if (cell.d[a][1] > z1)
-              ro->overflow[a][1] += axis_width (page, a, cell_ofs (z1),
-                                                cell_ofs (cell.d[a][1]));
+
+            if (overflow0)
+              {
+                ro->overflow[a][0] += p0 + axis_width (
+                  page, a, cell_ofs (cell.d[a][0]), cell_ofs (z0));
+                if (page->h[a][0] && page->h[a][1])
+                  ro->overflow[a][0] -= page->join_crossing[a][cell.d[a][0]
+                                                               + 1];
+              }
+
+            if (overflow1)
+              {
+                ro->overflow[a][1] += p1 + axis_width (
+                  page, a, cell_ofs (z1), cell_ofs (cell.d[a][1]));
+                if (page->h[a][0] && page->h[a][1])
+                  ro->overflow[a][1] -= page->join_crossing[a][cell.d[a][1]];
+              }
           }
+        z = cell.d[b][1];
         table_cell_free (&cell);
       }
 
   if (!page->h[a][1] || z1 < page->n[a] - page->h[a][1] || p1)
-    for (z = 0; z < page->n[b]; z++)
+    for (z = 0; z < page->n[b]; )
       {
         struct table_cell cell;
         int d[TABLE_N_AXES];
 
-        /* XXX need to handle p1 below */
         d[a] = z1 - 1;
         d[b] = z;
         table_get_cell (page->table, d[H], d[V], &cell);
-        if (z == cell.d[b][0] && cell.d[a][1] > z1
+        if ((cell.d[a][1] > z1 || (cell.d[a][1] == z1 && p1))
             && find_overflow_for_cell (&s, &cell) == NULL)
           {
             ro = insert_overflow (&s, &cell);
-            ro->overflow[a][1] += axis_width (page, a, cell_ofs (z1),
-                                              cell_ofs (cell.d[a][1]));
+            ro->overflow[a][1] += p1 + axis_width (page, a, cell_ofs (z1),
+                                                   cell_ofs (cell.d[a][1]));
           }
+        z = cell.d[b][1];
         table_cell_free (&cell);
       }
 
index 66ae86f7470bbd6083c71fdf7457fa260907c2f2..edbe49ebef4481aba1993106e9df872a44b8bf69 100644 (file)
@@ -477,6 +477,15 @@ AT_CHECK([render-test input], [0], [dnl
 |1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|
 +-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+])
+AT_CHECK([render-test input -o mb0 --min-break=0], [0], [dnl
++-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|
++-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 |30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
@@ -503,6 +512,19 @@ AT_CHECK([render-test input], [0], [dnl
 |ha|hb|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|hc|hd|
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
++--+--+--+--+--+--+--+
+|ha|hb|48|49|50|hc|hd|
++--+--+--+--+--+--+--+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 input], [0], [dnl
++--+--+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|ha|hb|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|hc|hd|
++--+--+-+-+-+-+-+-+-+-+-+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|ha|hb|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|hc|hd|
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
 +--+--+--+--+--+--+--+
 |ha|hb|48|49|50|hc|hd|
 +--+--+--+--+--+--+--+
@@ -536,6 +558,27 @@ AT_CHECK([render-test input], [0], [dnl
 |  46|  47|  48|  49|  50|
 +----+----+----+----+----+
 ])
+AT_CHECK([render-test -o mb0 --min-break=0 input], [0], [dnl
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cel
+|   1|   2|   3|   4|   5|   6|   7|   8|   9|  10|  11|  12|  13|  14|  15|  1
++----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+---
+
+-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--
+l|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|ce
+6|  17|  18|  19|  20|  21|  22|  23|  24|  25|  26|  27|  28|  29|  30|  31|
+-+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+--
+
+--+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-
+ll|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|c
+32|  33|  34|  35|  36|  37|  38|  39|  40|  41|  42|  43|  44|  45|  46|  47|
+--+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+-
+
+---+----+----+
+ell|cell|cell|
+ 48|  49|  50|
+---+----+----+
+])
 AT_CLEANUP
 
 AT_SETUP([breaking row of many medium-size cells, with headers])
@@ -573,6 +616,27 @@ header1|cell|cell|header2
        |  49|  50|
        +----+----+
 ])
+AT_CHECK([render-test -o mb0 --min-break=0 input], [0], [dnl
+       +----+----+----+----+----+----+----+----+----+----+----+----+--+
+header1|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|ce|header2
+       |   1|   2|   3|   4|   5|   6|   7|   8|   9|  10|  11|  12|  |
+       +----+----+----+----+----+----+----+----+----+----+----+----+--+
+
+       +--+----+----+----+----+----+----+----+----+----+----+----+----+
+header1|ll|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|header2
+       |13|  14|  15|  16|  17|  18|  19|  20|  21|  22|  23|  24|  25|
+       +--+----+----+----+----+----+----+----+----+----+----+----+----+
+
+       +----+----+----+----+----+----+----+----+----+----+----+----+--+
+header1|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|ce|header2
+       |  26|  27|  28|  29|  30|  31|  32|  33|  34|  35|  36|  37|  |
+       +----+----+----+----+----+----+----+----+----+----+----+----+--+
+
+       +--+----+----+----+----+----+----+----+----+----+----+----+----+
+header1|ll|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|cell|header2
+       |38|  39|  40|  41|  42|  43|  44|  45|  46|  47|  48|  49|  50|
+       +--+----+----+----+----+----+----+----+----+----+----+----+----+
+])
 AT_CLEANUP
 
 AT_SETUP([breaking row of many big narrow cells])
@@ -632,6 +696,57 @@ AT_CHECK([render-test input], [0], [dnl
 |of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|
 +------+------+------+------+------+------+
 ])
+AT_CHECK([render-test -o mb0 --min-break=0 input], [0], [dnl
++------+------+------+------+------+------+------+------+------+------+------+-
+|  This|  This|  This|  This|  This|  This|  This|  This|  This|  This|  This|
+|    is|    is|    is|    is|    is|    is|    is|    is|    is|    is|    is|
+|cell 1|cell 2|cell 3|cell 4|cell 5|cell 6|cell 7|cell 8|cell 9|  cell|  cell|
+|  in a|  in a|  in a|  in a|  in a|  in a|  in a|  in a|  in a| 10 in| 11 in|
+|series|series|series|series|series|series|series|series|series|     a|     a|
+|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|series|series|s
+|      |      |      |      |      |      |      |      |      |of 50.|of 50.|o
++------+------+------+------+------+------+------+------+------+------+------+-
+
+-----+------+------+------+------+------+------+------+------+------+------+---
+ This|  This|  This|  This|  This|  This|  This|  This|  This|  This|  This|  T
+   is|    is|    is|    is|    is|    is|    is|    is|    is|    is|    is|
+ cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  c
+12 in| 13 in| 14 in| 15 in| 16 in| 17 in| 18 in| 19 in| 20 in| 21 in| 22 in| 23
+    a|     a|     a|     a|     a|     a|     a|     a|     a|     a|     a|
+eries|series|series|series|series|series|series|series|series|series|series|ser
+f 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of
+-----+------+------+------+------+------+------+------+------+------+------+---
+
+---+------+------+------+------+------+------+------+------+------+------+-----
+his|  This|  This|  This|  This|  This|  This|  This|  This|  This|  This|  Thi
+ is|    is|    is|    is|    is|    is|    is|    is|    is|    is|    is|    i
+ell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cel
+ in| 24 in| 25 in| 26 in| 27 in| 28 in| 29 in| 30 in| 31 in| 32 in| 33 in| 34 i
+  a|     a|     a|     a|     a|     a|     a|     a|     a|     a|     a|
+ies|series|series|series|series|series|series|series|series|series|series|serie
+50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50
+---+------+------+------+------+------+------+------+------+------+------+-----
+
+-+------+------+------+------+------+------+------+------+------+------+------+
+s|  This|  This|  This|  This|  This|  This|  This|  This|  This|  This|  This|
+s|    is|    is|    is|    is|    is|    is|    is|    is|    is|    is|    is|
+l|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|  cell|
+n| 35 in| 36 in| 37 in| 38 in| 39 in| 40 in| 41 in| 42 in| 43 in| 44 in| 45 in|
+a|     a|     a|     a|     a|     a|     a|     a|     a|     a|     a|     a|
+s|series|series|series|series|series|series|series|series|series|series|series|
+.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|of 50.|
+-+------+------+------+------+------+------+------+------+------+------+------+
+
++------+------+------+------+------+
+|  This|  This|  This|  This|  This|
+|    is|    is|    is|    is|    is|
+|  cell|  cell|  cell|  cell|  cell|
+| 46 in| 47 in| 48 in| 49 in| 50 in|
+|     a|     a|     a|     a|     a|
+|series|series|series|series|series|
+|of 50.|of 50.|of 50.|of 50.|of 50.|
++------+------+------+------+------+
+])
 AT_CLEANUP
 
 AT_SETUP([breaking 2 rows of many small cells])
@@ -647,6 +762,19 @@ AT_CHECK([render-test input], [0], [dnl
 |51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+---+
+|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49| 50|
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+---+
+|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+---+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 input], [0], [dnl
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|
++--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+---+
 |27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49| 50|
 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+---+
@@ -680,12 +808,27 @@ AT_CHECK([render-test input], [0], [dnl
 45| 46| 47| 48| 49|50|
 --+---+---+---+---+--+
 ])
+AT_CHECK([render-test -o mb0 --min-break=0 input], [0], [dnl
+ a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M
++-+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
+|1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15| 16| 17| 18| 19| 20|
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+| 26| 27| 28| 29| 30| 31| 32| 33| 34| 35| 36| 37| 38| 39| 40| 41| 42| 43| 44| 4
++---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--
+
+ N O P Q R S T U V  W
++---+---+---+---+----+
+| 21| 22| 23| 24|  25|
++-+-+-+-+-+-+-+-+-+--+
+45| 46| 47| 48| 49|50|
+--+---+---+---+---+--+
+])
 AT_CLEANUP
 
 AT_SETUP([horz break 6x6, joined rows and columns])
 AT_KEYWORDS([render rendering])
 RENDER_WEAVE_6X6
-AT_CHECK([render-test --width=6 input], [0], [dnl
+AT_DATA([expout], [dnl
 +-+--
 |a|bc
 +-+-+
@@ -728,12 +871,14 @@ yz|s|
 |U|V|
 +-+-+
 ])
+AT_CHECK([render-test --width=6 input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=6 input], [0], [expout])
 AT_CLEANUP
 
 AT_SETUP([horz break 6x6, joined rows and columns, left header])
 AT_KEYWORDS([render rendering])
 RENDER_WEAVE_6X6([1 0 0 0])
-AT_CHECK([render-test --width=10 input], [0], [dnl
+AT_DATA([expout], [dnl
 +-+---+-+
 |a|bcd|e|
 +-+-+-+-+
@@ -762,12 +907,14 @@ AT_CHECK([render-test --width=10 input], [0], [dnl
 |Q|U|V|
 +-+-+-+
 ])
+AT_CHECK([render-test --width=10 input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=10 input], [0], [expout])
 AT_CLEANUP
 
 AT_SETUP([horz break 6x6, joined rows and columns, right header])
 AT_KEYWORDS([render rendering])
 RENDER_WEAVE_6X6([0 1 0 0])
-AT_CHECK([render-test --width=10 input], [0], [dnl
+AT_DATA([expout], [dnl
 +-+---+-+
 |a|bcd|i|
 +-+-+-+-+
@@ -796,6 +943,8 @@ op|h|q|
 |N|U|V|
 +-+-+-+
 ])
+AT_CHECK([render-test --width=10 input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=10 input], [0], [expout])
 AT_CLEANUP
 
 AT_SETUP([breaking joined cells too wide for page])
@@ -827,6 +976,31 @@ AT_CHECK([render-test --width=10 input], [0], [dnl
 |H|I|J|K|
 +-+-+-+-+
 
+----+
+ ghi|
+ jkl|
+----+
+ stu|
+ vwx|
++---+
+|EFG|
++-+-+
+|L|M|
++-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=10 input], [0], [dnl
++--------
+|abc def
+|
++-----+--
+|  mno|
+|  pqr|
++---+-+-+
+|yzA|BCD|
++-+-+-+-+
+|H|I|J|K|
++-+-+-+-+
+
 ----+
  ghi|
  jkl|
@@ -882,6 +1056,43 @@ qr|
 |J|K|
 +-+-+
 
+----+
+ ghi|
+ jkl|
+----+
+ stu|
+ vwx|
++---+
+|EFG|
++-+-+
+|L|M|
++-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=6 input], [0], [dnl
++----
+|abc
+|
++----
+|  mn
+|  pq
++---+
+|yzA|
++-+-+
+|H|I|
++-+-+
+
+-----
+ def
+
+--+--
+no|
+qr|
++-+-+
+|BCD|
++-+-+
+|J|K|
++-+-+
+
 ----+
  ghi|
  jkl|
@@ -911,6 +1122,17 @@ mnopqr
 
 stuvwx
 
+yz
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=6 input], [0], [dnl
+abcdef
+
+ghijkl
+
+mnopqr
+
+stuvwx
+
 yz
 ])
 AT_CLEANUP
@@ -921,17 +1143,13 @@ AT_CAPTURE_FILE([input])
 AT_DATA([input], [1 1
 @abcdefghijklmnopqrstuvwxyz
 ])
-AT_CHECK([render-test --width=6 input], [0], [dnl
+AT_DATA([expout], [dnl
 +-----
 |abcde
 +-----
 
 ------
-defghi
-------
-
-------
-hijklm
+fghijk
 ------
 
 ------
@@ -939,17 +1157,15 @@ lmnopq
 ------
 
 ------
-pqrstu
-------
-
-------
-tuvwxy
+rstuvw
 ------
 
 ---+
 xyz|
 ---+
 ])
+AT_CHECK([render-test --width=6 input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=6 input], [0], [expout])
 AT_CLEANUP
 
 AT_SETUP([horz break 8x8 with many 2x2 joins])
@@ -1024,6 +1240,77 @@ KL|  |
 
 | 456|
 | 789|
+|    |
++----+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=8 input], [0],[dnl
++---+--
+|abc|jk
+|def|  
+|ghi+--
+|   |yz
++-+-+BC
+|Q|V|EF
+|R| |  
+|S+-+-+
+|T|012|
+|U|345|
+| |678|
+| |   |
++-+-+-+
+|xyz|G|
+|ABC|H|
+|DEF|I|
+|   | |
++---+-+
+|abcde|
+|     |
++-----+
+
+--+----+
+kl| mno|
+  | pqr|
+--+ stu|
+zA|    |
+CD+-+--+
+FG|W| Z|
+  |X|  |
++-+Y+--+
+|9| | ab
+| | | de
++-+-+ gh
+|opq|   
+|rst+---
+|uvw| JK
+|   |   
++---+--+
+| MNOPQ|
+| RSTUV|
+| WXYZ0|
+|      |
++------+
+
++----+
+| vwx|
+|    |
++----+
+| HIJ|
+| KLM|
+| NOP|
+|    |
++-+--+
+bc| j|
+ef| k|
+hi| l|
+  | m|
+--+ n|
+KL|  |
+  |  |
++-+--+
+| 123|
+| 456|
+| 789|
+
 |    |
 +----+
 ])
@@ -1088,19 +1375,7 @@ AT_CHECK([render-test --length=10 input], [0], [dnl
 |20|
 +--+
 ])
-AT_CLEANUP
-
-AT_SETUP([breaking column of many small cells, with headers])
-AT_KEYWORDS([render rendering])
-AT_CAPTURE_FILE([input])
-AT_DATA([input], [17 1 0 0 1 1
-@a
-m4_for([x], [1], [15], [1], [@x
-])@b
-])
-AT_CHECK([render-test --length=13 input], [0], [dnl
-+--+
-| a|
+AT_CHECK([render-test -o mb0 --min-break=0 --length=10 input], [0], [dnl
 +--+
 | 1|
 +--+
@@ -1110,11 +1385,7 @@ AT_CHECK([render-test --length=13 input], [0], [dnl
 +--+
 | 4|
 +--+
-| b|
-+--+
 
-+--+
-| a|
 +--+
 | 5|
 +--+
@@ -1124,11 +1395,7 @@ AT_CHECK([render-test --length=13 input], [0], [dnl
 +--+
 | 8|
 +--+
-| b|
-+--+
 
-+--+
-| a|
 +--+
 | 9|
 +--+
@@ -1138,11 +1405,7 @@ AT_CHECK([render-test --length=13 input], [0], [dnl
 +--+
 |12|
 +--+
-| b|
-+--+
 
-+--+
-| a|
 +--+
 |13|
 +--+
@@ -1150,12 +1413,22 @@ AT_CHECK([render-test --length=13 input], [0], [dnl
 +--+
 |15|
 +--+
-| b|
+|16|
++--+
+
++--+
+|17|
++--+
+|18|
++--+
+|19|
++--+
+|20|
 +--+
 ])
 AT_CLEANUP
 
-AT_SETUP([disabling too-big headers])
+AT_SETUP([breaking column of many small cells, with headers])
 AT_KEYWORDS([render rendering])
 AT_CAPTURE_FILE([input])
 AT_DATA([input], [17 1 0 0 1 1
@@ -1163,7 +1436,7 @@ AT_DATA([input], [17 1 0 0 1 1
 m4_for([x], [1], [15], [1], [@x
 ])@b
 ])
-AT_CHECK([render-test --length=10 input], [0], [dnl
+AT_CHECK([render-test --length=13 input], [0], [dnl
 +--+
 | a|
 +--+
@@ -1172,14 +1445,134 @@ AT_CHECK([render-test --length=10 input], [0], [dnl
 | 2|
 +--+
 | 3|
-+--+
-
 +--+
 | 4|
 +--+
-| 5|
+| b|
 +--+
-| 6|
+
++--+
+| a|
++--+
+| 5|
++--+
+| 6|
++--+
+| 7|
++--+
+| 8|
++--+
+| b|
++--+
+
++--+
+| a|
++--+
+| 9|
++--+
+|10|
++--+
+|11|
++--+
+|12|
++--+
+| b|
++--+
+
++--+
+| a|
++--+
+|13|
++--+
+|14|
++--+
+|15|
++--+
+| b|
++--+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --length=13 input], [0], [dnl
++--+
+| a|
++--+
+| 1|
++--+
+| 2|
++--+
+| 3|
++--+
+| 4|
++--+
+| b|
++--+
+
++--+
+| a|
++--+
+| 5|
++--+
+| 6|
++--+
+| 7|
++--+
+| 8|
++--+
+| b|
++--+
+
++--+
+| a|
++--+
+| 9|
++--+
+|10|
++--+
+|11|
++--+
+|12|
++--+
+| b|
++--+
+
++--+
+| a|
++--+
+|13|
++--+
+|14|
++--+
+|15|
++--+
+| b|
++--+
+])
+AT_CLEANUP
+
+AT_SETUP([disabling too-big headers])
+AT_KEYWORDS([render rendering])
+AT_CAPTURE_FILE([input])
+AT_DATA([input], [17 1 0 0 1 1
+@a
+m4_for([x], [1], [15], [1], [@x
+])@b
+])
+AT_DATA([expout], [dnl
++--+
+| a|
++--+
+| 1|
++--+
+| 2|
++--+
+| 3|
++--+
+
++--+
+| 4|
++--+
+| 5|
++--+
+| 6|
 +--+
 | 7|
 +--+
@@ -1208,6 +1601,8 @@ AT_CHECK([render-test --length=10 input], [0], [dnl
 | b|
 +--+
 ])
+AT_CHECK([render-test --length=10 input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --length=10 input], [0], [expout])
 AT_CLEANUP
 
 AT_SETUP([breaking column of many medium-size cells])
@@ -1310,6 +1705,99 @@ AT_CHECK([render-test --length 10 input], [0], [dnl
 +---------+
 |   top 19|
 |  cell 19|
+|bottom 19|
++---------+
+|   top 20|
+|  cell 20|
+|bottom 20|
++---------+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --length 10 input], [0], [dnl
++---------+
+|    top 1|
+|   cell 1|
+| bottom 1|
++---------+
+|    top 2|
+|   cell 2|
+| bottom 2|
++---------+
+|    top 3|
+
+|   cell 3|
+| bottom 3|
++---------+
+|    top 4|
+|   cell 4|
+| bottom 4|
++---------+
+|    top 5|
+|   cell 5|
+
+| bottom 5|
++---------+
+|    top 6|
+|   cell 6|
+| bottom 6|
++---------+
+|    top 7|
+|   cell 7|
+| bottom 7|
++---------+
+
++---------+
+|    top 8|
+|   cell 8|
+| bottom 8|
++---------+
+|    top 9|
+|   cell 9|
+| bottom 9|
++---------+
+|   top 10|
+
+|  cell 10|
+|bottom 10|
++---------+
+|   top 11|
+|  cell 11|
+|bottom 11|
++---------+
+|   top 12|
+|  cell 12|
+
+|bottom 12|
++---------+
+|   top 13|
+|  cell 13|
+|bottom 13|
++---------+
+|   top 14|
+|  cell 14|
+|bottom 14|
++---------+
+
++---------+
+|   top 15|
+|  cell 15|
+|bottom 15|
++---------+
+|   top 16|
+|  cell 16|
+|bottom 16|
++---------+
+|   top 17|
+
+|  cell 17|
+|bottom 17|
++---------+
+|   top 18|
+|  cell 18|
+|bottom 18|
++---------+
+|   top 19|
+|  cell 19|
+
 |bottom 19|
 +---------+
 |   top 20|
@@ -1322,13 +1810,52 @@ AT_CLEANUP
 AT_SETUP([breaking 3 columns with many joined cells])
 AT_KEYWORDS([render rendering])
 AT_CAPTURE_FILE([input])
+#  +--+--+
+# a| 1|11|
+#  +--+ab|
+# b| 2|cd|
+#  |ab+--+
+# c|cd|12|
+#  +--+ab|
+# d| 3|cd|
+#  |ab+--+
+# e|cd|13|
+#  +--+ab|
+# f| 4|cd|
+#  |ab+--+
+# g|cd|14|
+#  +--+ab|
+# h| 5|cd|
+#  |ab+--+
+# i|cd|15|
+#  +--+ab|
+# j| 6|cd|
+#  |ab+--+
+# k|cd|16|
+#  +--+ab|
+# l| 7|cd|
+#  |ab+--+
+# m|cd|17|
+#  +--+ab|
+# n| 8|cd|
+#  |ab+--+
+# o|cd|18|
+#  +--+ab|
+# p| 9|cd|
+#  |ab+--+
+# q|cd|19|
+#  +--+ab|
+# r|10|cd|
+#  |ab+--+
+# s|cd|20|
+#  +--+--+
 AT_DATA([input], [3 19
 m4_foreach([x], [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s], [x
 ])@1
 m4_for([x], [2], [19], [1], [1*2 @x\nab\ncd
 ])@20
 ])
-AT_CHECK([render-test --length=6 --transpose input], [0], [dnl
+AT_DATA([expout], [dnl
  +--+--+
 a| 1|11|
  +--+ab|
@@ -1387,6 +1914,9 @@ r|10|cd|
 s|cd|20|
  +--+--+
 ])
+AT_CHECK([render-test --length=6 --transpose input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --length=6 --transpose input],
+  [0], [expout])
 AT_CLEANUP
 
 AT_SETUP([vert break 6x6, joined rows and columns])
@@ -1405,6 +1935,25 @@ AT_CHECK([render-test --length=6 input], [0], [dnl
 |A|v|B|E|FGH|
 +-+-+C+-+---+
 
++---+C+-+-+-+
+|IJK|D|L|O|P|
++-+-+-+M+-+-+
+|Q|RST|N|U|V|
++-+---+-+-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --length=6 input], [0], [dnl
++-+---+-+-+-+
+|a|bcd|e|f|i|
++-+-+-+-+g+-+
+|j|m|nop|h|q|
+|k+-+---+-+r|
+
+|k+-+-+---+r|
+|l|t|w|xyz|s|
++-+u+-+-+-+-+
+|A|v|B|E|FGH|
++-+-+C+-+---+
+
 +---+C+-+-+-+
 |IJK|D|L|O|P|
 +-+-+-+M+-+-+
@@ -1442,6 +1991,25 @@ AT_CHECK([render-test --transpose --length=6 input], [0], [dnl
 |stu|XYZ|qrs|F|
 |vwx|012+---+-+
 
+|vwx|012+---+-+
+|yzA|345|tuv|G|
+|BCD|678|wxy+-+
+|EFG|90a|zAB|H|
++---+---+---+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --transpose --length=6 input], [0], [dnl
++---+---+---+-+
+|abc|HIJ|bcd|C|
+|def|KLM|efg+-+
+|ghi|OPQ|hij|D|
+|jkl|RST+---+-+
+
+|jkl|RST+---+-+
+|mno|UVW|klm|E|
+|pqr+---+nop+-+
+|stu|XYZ|qrs|F|
+|vwx|012+---+-+
+
 |vwx|012+---+-+
 |yzA|345|tuv|G|
 |BCD|678|wxy+-+
@@ -1464,6 +2032,23 @@ AT_CHECK([render-test --width=6 --length=6 input], [0], [dnl
    opq
   rstu
 
+vwx yz
+ ABCDE
+ FGH I
+    JK
+ LMNOP
+QR STU
+
+ VWXYZ
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=6 --length=6 input], [0], [dnl
+   abc
+  defg
+   hij
+  klmn
+   opq
+  rstu
+
 vwx yz
  ABCDE
  FGH I
@@ -1481,7 +2066,7 @@ AT_CAPTURE_FILE([input])
 AT_DATA([input], [1 1
 @abc defg hij klmn opq rstu vwx yz ABCDE FGH I JK LMNOP QR STU VWXYZ
 ])
-AT_CHECK([render-test --width=7 --length=6 input], [0], [dnl
+AT_DATA([expout], [dnl
 +-----+
 |  abc|
 | defg|
@@ -1489,19 +2074,12 @@ AT_CHECK([render-test --width=7 --length=6 input], [0], [dnl
 | klmn|
 |  opq|
 
-| klmn|
-|  opq|
 | rstu|
 |  vwx|
-|   yz|
-|ABCDE|
-
 |   yz|
 |ABCDE|
 |FGH I|
 |   JK|
-|LMNOP|
-|   QR|
 
 |LMNOP|
 |   QR|
@@ -1509,6 +2087,9 @@ AT_CHECK([render-test --width=7 --length=6 input], [0], [dnl
 |VWXYZ|
 +-----+
 ])
+AT_CHECK([render-test --width=7 --length=6 input], [0], [expout])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=7 --length=6 input],
+  [0], [expout])
 AT_CLEANUP
 \f
 AT_BANNER([output rendering -- double page breaks])
@@ -1565,6 +2146,61 @@ yz|s|
 |FGH|
 +---+
 
++-+-+
+|O|P|
++-+-+
+|U|V|
++-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=6 --length=6 input], [0], [dnl
++-+--
+|a|bc
++-+-+
+|j|m|
+|k+-+
+
+|k+-+
+|l|t|
++-+u|
+|A|v|
++-+-+
+
++---+
+|IJK|
++-+-+
+|Q|RS
++-+--
+
+--+-+
+cd|e|
++-+-+
+|nop|
++---+
+
++-+--
+|w|xy
++-+-+
+|B|E|
+|C+-+
+
+|C+-+
+|D|L|
++-+M|
+ST|N|
+--+-+
+
++-+-+
+|f|i|
+|g+-+
+|h|q|
++-+r|
+
+--+r|
+yz|s|
++-+-+
+|FGH|
++---+
+
 +-+-+
 |O|P|
 +-+-+
@@ -1605,6 +2241,47 @@ AT_CHECK([render-test input --width=14 --length=14], [0], [dnl
 |u| A|s|D|
 +-+ B+-+-+
 
++-+ B+-+-+
+|E| C|M|P|
++-+--+N+-+
+|Q| X|O|Y|
++-+--+-+-+
+|Z|56|7|8|
++-+--+-+-+
+|9| efg|h|
++-+--+-+-+
+|i| n|o|p|
++-+--+-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 input --width=14 --length=14], [0], [dnl
++-+-+-+-+-+-+
+|a|b|c|d|e|h|
++-+-+-+-+-+-+
+|i|jkl|m|n|t|
++-+-+-+-+-+-+
+|u|v|wxy|z|D|
++-+-+-+-+-+-+
+|E|F|I|JKL|P|
++-+G+-+---+-+
+|Q|H|R|UVW|Y|
++-+-+S+-+-+-+
+|Z|0|T|3|4|8|
++-+1+-+-+-+-+
+
++-+1+---+-+-+
+|9|2|abc|d|h|
++-+-+-+-+-+-+
+|i|j|k|l|m|p|
++-+-+-+-+-+-+
+
++-+--+-+-+
+|a| f|g|h|
++-+--+-+-+
+|i|op|q|t|
++-+--+r+-+
+|u| A|s|D|
++-+ B+-+-+
+
 +-+ B+-+-+
 |E| C|M|P|
 +-+--+N+-+
@@ -1662,6 +2339,57 @@ AT_CHECK([render-test input --width=14 --length=14], [0], [dnl
 |o|p|
 +-+-+
 
++-+-+
+|g|h|
++-+-+
+|7|8|
+| | |
++-+-+
+fg|h|
++-+-+
+|o|p|
++-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 input --width=14 --length=14], [0], [dnl
++-+-+-+-+-+-+
+|a|b|c|d|e|f|
++-+-+-+-+-+-+
+|i|jkl|m|nop|
++-+-+-+-+-+-+
+|u|v|wxy|z|A|
++-+-+-+-+-+B|
+|E|F|I|JKL|C|
++-+G+-+---+-+
+|Q|H|R|UVW|X|
++-+-+-+-+-+-+
+|i|j|k|l|m|n|
++-+-+-+-+-+-+
+
++-+-+-+-+-+-+
+|a|b|c|d|e|f|
++-+-+-+-+-+-+
+|Z|0|S|3|456|
+| |1|T| |   |
++-+2+-+-+-+-+
+|9| |abc|d|ef
++-+-+-+-+-+-+
+|i|j|k|l|m|n|
++-+-+-+-+-+-+
+
++-+-+
+|g|h|
++-+-+
+|q|t|
+|r+-+
+|s|D|
++-+-+
+|M|P|
+|N+-+
+|O|Y|
++-+-+
+|o|p|
++-+-+
+
 +-+-+
 |g|h|
 +-+-+
@@ -1718,6 +2446,57 @@ AT_CHECK([render-test input --width=14 --length=14], [0], [dnl
 |i| n|o|p|
 +-+--+-+-+
 
++-+--+-+-+
+|a| f|g|h|
++-+--+-+-+
+|Z|56|7|8|
+| |  | | |
++-+--+-+-+
+|9| efg|h|
++-+--+-+-+
+|i| n|o|p|
++-+--+-+-+
+])
+AT_CHECK([render-test -o mb0 --min-break=0 input --width=14 --length=14], [0], [dnl
++-+-+-+-+-+-+
+|a|b|c|d|e|h|
++-+-+-+-+-+-+
+|i|jkl|m|n|t|
++-+-+-+-+-+-+
+|u|v|wxy|z|D|
++-+-+-+-+-+-+
+|E|F|I|JKL|P|
++-+G+-+---+-+
+|Q|H|R|UVW|Y|
++-+-+-+-+-+-+
+|i|j|k|l|m|p|
++-+-+-+-+-+-+
+
++-+-+-+-+-+-+
+|a|b|c|d|e|h|
++-+-+-+-+-+-+
+|Z|0|S|3|4|8|
+| |1|T| | | |
++-+2+-+-+-+-+
+|9| |abc|d|h|
++-+-+-+-+-+-+
+|i|j|k|l|m|p|
++-+-+-+-+-+-+
+
++-+--+-+-+
+|a| f|g|h|
++-+--+-+-+
+|i|op|q|t|
++-+--+r+-+
+|u| A|s|D|
++-+ B+-+-+
+|E| C|M|P|
++-+--+N+-+
+|Q| X|O|Y|
++-+--+-+-+
+|i| n|o|p|
++-+--+-+-+
+
 +-+--+-+-+
 |a| f|g|h|
 +-+--+-+-+
@@ -1806,6 +2585,62 @@ excluded.|
          |
 ---------+
 ])
+AT_CHECK([render-test -o mb0 --min-break=0 --width=15 --length=15 input], [0], [dnl
++-+--+--+---+-
+|a| b| c|  d|
++-+--+--+---+-
+|h|       The
+| |        sub
++-+    determi
+|i|       hand
+| |missing var
+| |If INCLUDE
++-+ then user‑
+|j|        val
+| |   included
+| | calculatio
++-+ NOINCLUDE
+|k|      which
+
+| |          d
+| |      user‑
++-+        val
+|l|         ex
+| |
+| |
++-+
+|m|
+| |
++-+-----------
+
+-+--+--+
+e| f| g|
+-+--+--+
+MISSING|
+
+command|
+nes the|
+ling of|
+iables.|
+is set,|
+missing|
+ues are|
+ in the|
+ns.  If|
+is set,|
+ is the|
+efault,|
+missing|
+ues are|
+cluded.|
+
+       |
+       |
+       |
+       |
+       |
+-------+
+])
 AT_CLEANUP
 \f
 AT_BANNER([output rendering -- problematic procedures])