+ struct mmain *p;
+ const struct mdoc *mdoc;
+ struct termp termp;
+
+ p = mmain_alloc();
+
+ if ( ! mmain_getopt(p, argc, argv, NULL, NULL, NULL, NULL))
+ mmain_exit(p, 1);
+
+ if (NULL == (mdoc = mmain_mdoc(p)))
+ mmain_exit(p, 1);
+
+ termp.maxrmargin = 80; /* XXX */
+ termp.rmargin = termp.maxrmargin;
+ termp.maxcols = 1024;
+ termp.offset = termp.col = 0;
+ termp.flags = TERMP_NOSPACE;
+
+ if (NULL == (termp.buf = malloc(termp.maxcols)))
+ err(1, "malloc");
+
+ header(&termp, mdoc_meta(mdoc));
+ body(&termp, NULL, mdoc_meta(mdoc), mdoc_node(mdoc));
+ footer(&termp, mdoc_meta(mdoc));
+
+ free(termp.buf);
+
+ mmain_exit(p, 0);
+ /* NOTREACHED */
+}
+
+
+void
+flushln(struct termp *p)
+{
+ size_t i, j, vsz, vis, maxvis;
+
+ /*
+ * First, establish the maximum columns of "visible" content.
+ * This is usually the difference between the right-margin and
+ * an indentation, but can be, for tagged lists or columns, a
+ * small set of values.
+ */
+
+ assert(p->offset < p->rmargin);
+ maxvis = p->rmargin - p->offset;
+ vis = 0;
+
+ /*
+ * If in the standard case (left-justified), then begin with our
+ * indentation, otherwise (columns, etc.) just start spitting
+ * out text.
+ */
+
+ if ( ! (p->flags & TERMP_NOLPAD))
+ /* LINTED */
+ for (j = 0; j < p->offset; j++)
+ putchar(' ');
+
+ /*
+ * If we're literal, print out verbatim.
+ */
+ if (p->flags & TERMP_LITERAL) {
+ /* FIXME: count non-printing chars. */
+ for (i = 0; i < p->col; i++)
+ putchar(p->buf[i]);
+ putchar('\n');
+ p->col = 0;
+ return;
+ }
+
+ for (i = 0; i < p->col; i++) {
+ /*
+ * Count up visible word characters. Control sequences
+ * (starting with the CSI) aren't counted.
+ */
+ assert( ! xisspace(p->buf[i]));
+
+ /* LINTED */
+ for (j = i, vsz = 0; j < p->col; j++) {
+ if (xisspace(p->buf[j]))
+ break;
+ else if (27 == p->buf[j]) {
+ assert(j + 4 <= p->col);
+ j += 3;
+ } else
+ vsz++;
+ }
+ assert(vsz > 0);
+
+ /*
+ * If a word is too long and we're within a line, put it
+ * on the next line. Puke if we're being asked to write
+ * something that will exceed the right margin (i.e.,
+ * from a fresh line or when we're not allowed to break
+ * the line with TERMP_NOBREAK).
+ */
+
+ if (vis && vis + vsz >= maxvis) {
+ /* FIXME */
+ if (p->flags & TERMP_NOBREAK)
+ errx(1, "word breaks right margin");
+ putchar('\n');
+ for (j = 0; j < p->offset; j++)
+ putchar(' ');
+ vis = 0;
+ } else if (vis + vsz >= maxvis)
+ /* FIXME */
+ errx(1, "word breaks right margin");
+
+ /*
+ * Write out the word and a trailing space. Omit the
+ * space if we're the last word in the line.
+ */
+
+ for ( ; i < p->col; i++) {
+ if (xisspace(p->buf[i]))
+ break;
+ putchar(p->buf[i]);