#include "gl/minmax.h"
#include "gl/xalloc.h"
+#include "gl/xsize.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
/* User parameters. */
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. */
char *chart_file_name; /* Name of files used for charts. */
#endif
int width; /* Page width. */
- int length; /* Page length minus margins and header. */
bool auto_width; /* Use viewwidth as page width? */
- bool auto_length; /* Use viewlength as page width? */
-
- 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. */
/* Internal state. */
char *command_name;
- char *title;
- char *subtitle;
struct file_handle *handle;
FILE *file; /* Output file. */
bool error; /* Output error? */
- int page_number; /* Current page number. */
struct u8_line *lines; /* Page content. */
int allocated_lines; /* Number of lines allocated. */
int chart_cnt; /* Number of charts so far. */
- int x, 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 bool update_page_size (struct ascii_driver *, bool issue_error);
static int parse_page_size (struct driver_option *);
-static void ascii_close_page (struct ascii_driver *);
static bool ascii_open_page (struct ascii_driver *);
static void ascii_draw_line (void *, int bb[TABLE_N_AXES][2],
int footnote_idx, int bb[TABLE_N_AXES][2],
int clip[TABLE_N_AXES][2]);
-static void
-reallocate_lines (struct ascii_driver *a)
-{
- if (a->length > a->allocated_lines)
- {
- int i;
- a->lines = xnrealloc (a->lines, a->length, sizeof *a->lines);
- for (i = a->allocated_lines; i < a->length; i++)
- u8_line_init (&a->lines[i]);
- a->allocated_lines = a->length;
- }
-}
-
-
static struct ascii_driver *
ascii_driver_cast (struct output_driver *driver)
{
int min_break[TABLE_N_AXES];
struct output_driver *d;
struct ascii_driver *a;
- int paper_length;
a = xzalloc (sizeof *a);
d = &a->driver;
output_driver_init (&a->driver, &ascii_driver_class, fh_get_file_name (fh), device_type);
a->append = parse_boolean (opt (d, o, "append", "false"));
- 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,
a->chart_file_name = parse_chart_file_name (opt (d, o, "charts", fh_get_file_name (fh)));
a->handle = fh;
- 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);
a->box = box == BOX_ASCII ? ascii_box_chars : unicode_box_chars;
a->command_name = NULL;
- a->title = xstrdup ("");
- a->subtitle = xstrdup ("");
a->file = NULL;
a->error = false;
- a->page_number = 0;
a->lines = NULL;
a->allocated_lines = 0;
a->chart_cnt = 1;
return dim;
}
-static int
-vertical_margins (const struct ascii_driver *a)
-{
- return a->top_margin + a->bottom_margin + (a->headers ? 3 : 0);
-}
-
-/* Re-calculates the page width and length based on settings,
- margins, and, if "auto" is set, the size of the user's
- terminal window or GUI output window. */
+/* Re-calculates the page width based on settings, margins, and, if "auto" is
+ set, the size of the user's terminal window or GUI output window. */
static bool
update_page_size (struct ascii_driver *a, bool issue_error)
{
a->width = settings_get_viewwidth ();
a->min_break[H] = a->width / 2;
}
- if (a->auto_length)
- {
- a->length = settings_get_viewlength () - vertical_margins (a);
- a->min_break[V] = a->length / 2;
- }
- if (a->width < MIN_WIDTH || a->length < MIN_LENGTH)
+ if (a->width < MIN_WIDTH)
{
if (issue_error)
msg (ME,
- _("ascii: page excluding margins and headers "
- "must be at least %d characters wide by %d lines long, but "
- "as configured is only %d characters by %d lines"),
- MIN_WIDTH, MIN_LENGTH,
- a->width, a->length);
+ _("ascii: page must be at least %d characters wide, but "
+ "as configured is only %d characters"),
+ MIN_WIDTH,
+ a->width);
if (a->width < MIN_WIDTH)
a->width = MIN_WIDTH;
- if (a->length < MIN_LENGTH)
- a->length = MIN_LENGTH;
return false;
}
- reallocate_lines (a);
-
return true;
}
struct ascii_driver *a = ascii_driver_cast (driver);
int i;
- if (a->y > 0)
- ascii_close_page (a);
-
if (a->file != NULL)
fn_close (a->handle, a->file);
fh_unref (a->handle);
free (a->command_name);
- free (a->title);
- free (a->subtitle);
free (a->chart_file_name);
for (i = 0; i < a->allocated_lines; i++)
u8_line_destroy (&a->lines[i]);
ascii_flush (struct output_driver *driver)
{
struct ascii_driver *a = ascii_driver_cast (driver);
- if (a->y > 0)
+ if (a->file)
+ fflush (a->file);
+}
+
+static void
+ascii_output_lines (struct ascii_driver *a, size_t n_lines)
+{
+ for (size_t y = 0; y < n_lines; y++)
{
- ascii_close_page (a);
+ struct u8_line *line = &a->lines[y];
+
+ while (ds_chomp_byte (&line->s, ' '))
+ continue;
+ fwrite (ds_data (&line->s), 1, ds_length (&line->s), a->file);
+ putc ('\n', a->file);
- if (fn_close (a->handle, a->file) != 0)
- msg_error (errno, _("ascii: closing output file `%s'"), fh_get_file_name (a->handle));
- a->file = NULL;
+ u8_line_clear (&a->lines[y]);
}
}
params.draw_cell = ascii_draw_cell;
params.aux = a;
params.size[H] = a->width;
- params.size[V] = a->length;
+ params.size[V] = INT_MAX;
params.font_size[H] = 1;
params.font_size[V] = 1;
for (i = 0; i < RENDER_N_LINES; i++)
params.min_break[i] = a->min_break[i];
params.supports_margins = false;
- if (a->file == NULL && !ascii_open_page (a))
+ if (a->file)
+ putc ('\n', a->file);
+ else if (!ascii_open_page (a))
return;
p = render_pager_create (¶ms, table_item);
- while (render_pager_has_next (p))
+ for (int i = 0; render_pager_has_next (p); i++)
{
- int used;
-
- if (a->y > 0)
- a->y++;
- used = render_pager_draw_next (p, a->length - a->y);
- if (used == 0)
- {
- /* Make sure that we're not in a loop where the table we're rendering
- can't be broken to fit on a page. (The check on
- render_pager_has_next() allows for objects that turn out to be
- empty when we try to render them.) */
- assert (a->y > 0 || !render_pager_has_next (p));
-
- ascii_close_page (a);
- if (!ascii_open_page (a))
- break;
- }
- else
- a->y += used;
+ if (i)
+ putc ('\n', a->file);
+ ascii_output_lines (a, render_pager_draw_next (p, INT_MAX));
}
render_pager_destroy (p);
}
switch (type)
{
case TEXT_ITEM_TITLE:
- free (a->title);
- a->title = xstrdup (text);
- break;
-
case TEXT_ITEM_SUBTITLE:
- free (a->subtitle);
- a->subtitle = xstrdup (text);
- break;
-
case TEXT_ITEM_COMMAND_OPEN:
case TEXT_ITEM_COMMAND_CLOSE:
break;
case TEXT_ITEM_BLANK_LINE:
- if (a->y > 0)
- a->y++;
break;
case TEXT_ITEM_EJECT_PAGE:
- if (a->y > 0)
- ascii_close_page (a);
break;
default:
int x, y;
/* Clip to the page. */
- x0 = MAX (bb[H][0] + a->x, 0);
- y0 = MAX (bb[V][0] + a->y, 0);
- x1 = MIN (bb[H][1] + a->x, a->width);
- y1 = MIN (bb[V][1] + a->y, a->length);
- if (x1 <= 0 || y1 <= 0 || x0 >= a->width || y0 >= a->length)
+ x0 = MAX (bb[H][0], 0);
+ y0 = MAX (bb[V][0], 0);
+ x1 = MIN (bb[H][1], a->width);
+ y1 = bb[V][1];
+ if (x1 <= 0 || y1 <= 0 || x0 >= a->width)
return;
/* Draw. */
static char *
ascii_reserve (struct ascii_driver *a, int y, int x0, int x1, int n)
{
- assert (y < a->allocated_lines);
+ if (y >= a->allocated_lines)
+ {
+ size_t new_alloc = MAX (25, a->allocated_lines);
+ while (new_alloc <= y)
+ new_alloc = xtimes (new_alloc, 2);
+ a->lines = xnrealloc (a->lines, new_alloc, sizeof *a->lines);
+ for (size_t i = a->allocated_lines; i < new_alloc; i++)
+ u8_line_init (&a->lines[i]);
+ a->allocated_lines = new_alloc;
+ }
return u8_line_reserve (&a->lines[y], x0, x1, n);
}
int bb[TABLE_N_AXES][2], int clip[TABLE_N_AXES][2],
int y, const uint8_t *string, int n, size_t width)
{
- int x0 = MAX (0, clip[H][0] + a->x);
- int y0 = MAX (0, clip[V][0] + a->y);
- int x1 = MIN (a->width, clip[H][1] + a->x);
- int y1 = MIN (a->length, clip[V][1] + a->y);
+ int x0 = MAX (0, clip[H][0]);
+ int y0 = MAX (0, clip[V][0]);
+ int x1 = MIN (a->width, clip[H][1]);
+ int y1 = clip[V][1];
int x;
- y += a->y;
if (y < y0 || y >= y1)
return;
default:
NOT_REACHED ();
}
- x += a->x;
if (x >= x1)
return;
if (a->file == NULL && !ascii_open_page (a))
return;
- a->y = 0;
contents.options = options | TAB_LEFT;
contents.text = CONST_CAST (char *, s);
bb[TABLE_HORZ][0] = x;
bb[TABLE_HORZ][1] = a->width;
bb[TABLE_VERT][0] = y;
- bb[TABLE_VERT][1] = a->length;
+ bb[TABLE_VERT][1] = INT_MAX;
ascii_layout_cell (a, &cell, 0, bb, bb, &width, &height);
-
- a->y = 1;
}
void
if (a->file == NULL && !ascii_open_page (a))
return;
- if (y < 0 || y >= a->length)
+ if (y < 0)
return;
u8_line_set_length (&a->lines[y], length);
}
+
+void
+ascii_test_flush (struct output_driver *driver)
+{
+ struct ascii_driver *a = ascii_driver_cast (driver);
+
+ for (size_t i = a->allocated_lines; i-- > 0; )
+ if (a->lines[i].width)
+ {
+ ascii_output_lines (a, i + 1);
+ break;
+ }
+}
\f
/* ascii_close_page () and support routines. */
static bool
ascii_open_page (struct ascii_driver *a)
{
- int i;
-
if (a->error)
return false;
sigaction (SIGWINCH, &action, NULL);
#endif
a->auto_width = true;
- a->auto_length = true;
}
}
else
}
}
- a->page_number++;
-
- reallocate_lines (a);
-
- for (i = 0; i < a->length; i++)
- u8_line_clear (&a->lines[i]);
-
return true;
}
-
-static void
-output_title_line (FILE *out, int width, const char *left, const char *right)
-{
- struct string s = DS_EMPTY_INITIALIZER;
- ds_put_byte_multiple (&s, ' ', width);
- if (left != NULL)
- {
- size_t length = MIN (strlen (left), width);
- memcpy (ds_end (&s) - width, left, length);
- }
- if (right != NULL)
- {
- size_t length = MIN (strlen (right), width);
- memcpy (ds_end (&s) - length, right, length);
- }
- ds_put_byte (&s, '\n');
- fputs (ds_cstr (&s), out);
- ds_destroy (&s);
-}
-
-static void
-ascii_close_page (struct ascii_driver *a)
-{
- bool any_blank;
- int i, y;
-
- a->y = 0;
- if (a->file == NULL)
- return;
-
- if (!a->top_margin && !a->bottom_margin && a->squeeze_blank_lines
- && !a->paginate && a->page_number > 1)
- putc ('\n', a->file);
-
- for (i = 0; i < a->top_margin; i++)
- putc ('\n', a->file);
- if (a->headers)
- {
- char *r1, *r2;
-
- r1 = xasprintf (_("%s - Page %d"), get_start_date (), a->page_number);
- r2 = xasprintf ("%s - %s" , version, host_system);
-
- output_title_line (a->file, a->width, a->title, r1);
- output_title_line (a->file, a->width, a->subtitle, r2);
- putc ('\n', a->file);
-
- free (r1);
- free (r2);
- }
-
- any_blank = false;
- for (y = 0; y < a->allocated_lines; y++)
- {
- struct u8_line *line = &a->lines[y];
-
- if (a->squeeze_blank_lines && y > 0 && line->width == 0)
- any_blank = true;
- else
- {
- if (any_blank)
- {
- putc ('\n', a->file);
- any_blank = false;
- }
-
- while (ds_chomp_byte (&line->s, ' '))
- continue;
- fwrite (ds_data (&line->s), 1, ds_length (&line->s), a->file);
- putc ('\n', a->file);
- }
- }
- if (!a->squeeze_blank_lines)
- for (y = a->allocated_lines; y < a->length; y++)
- putc ('\n', a->file);
-
- for (i = 0; i < a->bottom_margin; i++)
- putc ('\n', a->file);
- if (a->paginate)
- putc ('\f', a->file);
-}
| |
+-+--+
| 123|
-| 456|
-
| 456|
| 789|
| |
| 123|
| 456|
| 789|
-
| |
+----+
])
AT_CLEANUP
\f
-AT_BANNER([output rendering -- vertical page breaks])
-
-AT_SETUP([breaking column of many small cells])
-AT_KEYWORDS([render rendering])
-AT_CAPTURE_FILE([input])
-AT_DATA([input], [20 1
-m4_for([x], [1], [20], [1], [@x
-])])
-AT_CHECK([render-test --length=10 input], [0], [dnl
-+--+
-| 1|
-+--+
-| 2|
-+--+
-| 3|
-+--+
-| 4|
-+--+
-
-+--+
-| 5|
-+--+
-| 6|
-+--+
-| 7|
-+--+
-| 8|
-+--+
-
-+--+
-| 9|
-+--+
-|10|
-+--+
-|11|
-+--+
-|12|
-+--+
-
-+--+
-|13|
-+--+
-|14|
-+--+
-|15|
-+--+
-|16|
-+--+
-
-+--+
-|17|
-+--+
-|18|
-+--+
-|19|
-+--+
-|20|
-+--+
-])
-AT_CHECK([render-test -o mb0 --min-break=0 --length=10 input], [0], [dnl
-+--+
-| 1|
-+--+
-| 2|
-+--+
-| 3|
-+--+
-| 4|
-+--+
-
-+--+
-| 5|
-+--+
-| 6|
-+--+
-| 7|
-+--+
-| 8|
-+--+
-
-+--+
-| 9|
-+--+
-|10|
-+--+
-|11|
-+--+
-|12|
-+--+
-
-+--+
-|13|
-+--+
-|14|
-+--+
-|15|
-+--+
-|16|
-+--+
-
-+--+
-|17|
-+--+
-|18|
-+--+
-|19|
-+--+
-|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|
-+--+
-| 1|
-+--+
-| 2|
-+--+
-| 3|
-+--+
-| 4|
-+--+
-| b|
-+--+
-
-+--+
-| 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|
-+--+
-
-+--+
-| 8|
-+--+
-| 9|
-+--+
-|10|
-+--+
-|11|
-+--+
-
-+--+
-|12|
-+--+
-|13|
-+--+
-|14|
-+--+
-|15|
-+--+
-
-+--+
-| 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])
-AT_KEYWORDS([render rendering])
-AT_CAPTURE_FILE([input])
-AT_DATA([input], [20 1
-m4_for([x], [1], [20], [1], [@top x\ncell x\nbottom x
-])])
-AT_CHECK([render-test --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|
-| 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|
-| cell 20|
-|bottom 20|
-+---------+
-])
-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_DATA([expout], [dnl
- +--+--+
-a| 1|11|
- +--+ab|
-b| 2|cd|
- |ab+--+
-
- |ab+--+
-c|cd|12|
- +--+ab|
-d| 3|cd|
- |ab+--+
-
- |ab+--+
-e|cd|13|
- +--+ab|
-f| 4|cd|
- |ab+--+
-
- |ab+--+
-g|cd|14|
- +--+ab|
-h| 5|cd|
- |ab+--+
-
- |ab+--+
-i|cd|15|
- +--+ab|
-j| 6|cd|
- |ab+--+
-
- |ab+--+
-k|cd|16|
- +--+ab|
-l| 7|cd|
- |ab+--+
-
- |ab+--+
-m|cd|17|
- +--+ab|
-n| 8|cd|
- |ab+--+
-
- |ab+--+
-o|cd|18|
- +--+ab|
-p| 9|cd|
- |ab+--+
-
- |ab+--+
-q|cd|19|
- +--+ab|
-r|10|cd|
- |ab+--+
-
- |ab+--+
-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])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [WEAVE_6X6])
-AT_CHECK([render-test --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+-+-+
-|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+-+-+
-|Q|RST|N|U|V|
-+-+---+-+-+-+
-])
-AT_CLEANUP
-
-AT_SETUP([breaking joined cells too tall for page])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [4 6
-1*6 @abc\ndef\nghi\njkl\nmno\npqr\nstu\nvwx\nyzA\nBCD\nEFG
-1*3 @HIJ\nKLM\nOPQ\nRST\nUVW
-1*3 @XYZ\n012\n345\n678\n90a
-1*2 @bcd\nefg\nhij
-1*2 @klm\nnop\nqrs
-1*2 @tuv\nwxy\nzAB
-@C
-@D
-@E
-@F
-@G
-@H
-])
-AT_CHECK([render-test --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+-+
-|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+-+
-|EFG|90a|zAB|H|
-+---+---+---+-+
-])
-AT_CLEANUP
-
-AT_SETUP([breaking cell too tall for page, no border])
-AT_KEYWORDS([render rendering])
-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=6 --length=6 input], [0], [dnl
- abc
- defg
- hij
- klmn
- 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
- JK
- LMNOP
-QR STU
-
- VWXYZ
-])
-AT_CLEANUP
-
-AT_SETUP([breaking cell too tall for page, with border])
-AT_KEYWORDS([render rendering])
-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_DATA([expout], [dnl
-+-----+
-| 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], [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])
-
-AT_SETUP([double break 6x6, joined rows and columns])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [WEAVE_6X6])
-AT_CHECK([render-test --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|
-+-+-+
-|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|
-+-+-+
-|U|V|
-+-+-+
-])
-AT_CLEANUP
-
-AT_SETUP([double break 8x8, with joins, left and right headers])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [WEAVE_8X8([1 1 0 0])])
-AT_CHECK([render-test 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+-+
-|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+-+
-|Q| X|O|Y|
-+-+--+-+-+
-|Z|56|7|8|
-+-+--+-+-+
-|9| efg|h|
-+-+--+-+-+
-|i| n|o|p|
-+-+--+-+-+
-])
-AT_CLEANUP
-
-AT_SETUP([double break 8x8, with joins, top and bottom headers])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [WEAVE_8X8([0 0 1 1])])
-AT_CHECK([render-test 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|
-+-+-+
-|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|
-+-+-+
-|7|8|
-| | |
-+-+-+
-fg|h|
-+-+-+
-|o|p|
-+-+-+
-])
-AT_CLEANUP
-
-AT_SETUP([double break 8x8, with joins, all headers])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [WEAVE_8X8([1 1 1 1])])
-AT_CHECK([render-test 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|
-+-+--+-+-+
-|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|
-+-+--+-+-+
-|Z|56|7|8|
-| | | | |
-+-+--+-+-+
-|9| efg|h|
-+-+--+-+-+
-|i| n|o|p|
-+-+--+-+-+
-])
-AT_CLEANUP
-
-AT_SETUP([double break joined cells too big for page])
-AT_KEYWORDS([render rendering])
-AT_DATA([input], [7 7
-@a
-@b
-@c
-@d
-@e
-@f
-@g
-@h
-6*6 @The MISSING subcommand determines the handling of missing variables. If INCLUDE is set, then user‑missing values are included in the calculations. If NOINCLUDE is set, which is the default, user‑missing values are excluded.
-@i
-@j
-@k
-@l
-@m
-])
-AT_CHECK([render-test --width=15 --length=15 input], [0], [dnl
-+-+--+--+---+
-|a| b| c| d|
-+-+--+--+---+
-|h| The
-| | su
-+-+ determ
-|i| han
-| |missing va
-| |If INCLUDE
-+-+ then user
-|j| va
-| | include
-| | calculati
-+-+ NOINCLUDE
-
-+-+ NOINCLUDE
-|k| whic
-| |
-| | user
-+-+ va
-|l| e
-| |
-| |
-+-+
-|m|
-| |
-+-+----------
-
-+--+--+--+
-| e| f| g|
-+--+--+--+
-e MISSING|
-ubcommand|
-mines the|
-ndling of|
-ariables.|
-E is set,|
-r‑missing|
-alues are|
-ed in the|
-ions. If|
-E is set,|
-
-E is set,|
-ch is the|
- default,|
-r‑missing|
-alues are|
-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])
dnl LIST used to put columns right up next to each other without any