summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--Makefile.depend1
-rw-r--r--man_term.c4
-rw-r--r--mdoc_man.c12
-rw-r--r--mdoc_term.c38
-rw-r--r--regress/roff/Makefile2
-rw-r--r--regress/roff/ta/Makefile5
-rw-r--r--regress/roff/ta/basic-man.in19
-rw-r--r--regress/roff/ta/basic-man.out_ascii22
-rw-r--r--regress/roff/ta/basic-mdoc.in34
-rw-r--r--regress/roff/ta/basic-mdoc.out_ascii25
-rw-r--r--roff.c30
-rw-r--r--roff.h2
-rw-r--r--roff_html.c1
-rw-r--r--roff_term.c12
-rw-r--r--roff_validate.c1
-rw-r--r--term.c25
-rw-r--r--term.h4
-rw-r--r--term_ascii.c1
-rw-r--r--term_tab.c117
20 files changed, 326 insertions, 31 deletions
diff --git a/Makefile b/Makefile
index f75c7320..1964818d 100644
--- a/Makefile
+++ b/Makefile
@@ -125,6 +125,7 @@ SRCS = att.c \
term.c \
term_ascii.c \
term_ps.c \
+ term_tab.c \
tree.c
DISTFILES = INSTALL \
@@ -260,6 +261,7 @@ MANDOC_TERM_OBJS = eqn_term.o \
term.o \
term_ascii.o \
term_ps.o \
+ term_tab.o \
tbl_term.o
DBM_OBJS = dbm.o \
diff --git a/Makefile.depend b/Makefile.depend
index b75befd8..61d967af 100644
--- a/Makefile.depend
+++ b/Makefile.depend
@@ -72,4 +72,5 @@ tbl_term.o: tbl_term.c config.h mandoc.h out.h term.h
term.o: term.c config.h mandoc.h mandoc_aux.h out.h term.h main.h
term_ascii.o: term_ascii.c config.h mandoc.h mandoc_aux.h out.h term.h manconf.h main.h
term_ps.o: term_ps.c config.h mandoc_aux.h out.h term.h manconf.h main.h
+term_tab.o: term_tab.c mandoc_aux.h out.h term.h
tree.o: tree.c config.h mandoc.h roff.h mdoc.h man.h main.h
diff --git a/man_term.c b/man_term.c
index 19ce0eb8..653788ff 100644
--- a/man_term.c
+++ b/man_term.c
@@ -142,7 +142,9 @@ terminal_man(void *arg, const struct roff_man *man)
p = (struct termp *)arg;
p->overstep = 0;
p->rmargin = p->maxrmargin = p->defrmargin;
- p->tabwidth = term_len(p, 5);
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, ".5i");
memset(&mt, 0, sizeof(struct mtermp));
mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
diff --git a/mdoc_man.c b/mdoc_man.c
index 567d1788..fb4d17e1 100644
--- a/mdoc_man.c
+++ b/mdoc_man.c
@@ -112,6 +112,7 @@ static void pre_sp(DECL_ARGS);
static int pre_sect(DECL_ARGS);
static int pre_sy(DECL_ARGS);
static void pre_syn(const struct roff_node *);
+static void pre_ta(DECL_ARGS);
static int pre_vt(DECL_ARGS);
static int pre_xr(DECL_ARGS);
static void print_word(const char *);
@@ -128,6 +129,7 @@ static const void_fp roff_manacts[ROFF_MAX] = {
pre_ft,
pre_ll,
pre_sp,
+ pre_ta,
};
static const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
@@ -443,7 +445,6 @@ static void
print_line(const char *s, int newflags)
{
- outflags &= ~MMAN_br;
outflags |= MMAN_nl;
print_word(s);
outflags |= newflags;
@@ -1715,6 +1716,15 @@ pre_sy(DECL_ARGS)
return 1;
}
+static void
+pre_ta(DECL_ARGS)
+{
+ print_line(".ta", 0);
+ for (n = n->child; n != NULL; n = n->next)
+ print_word(n->string);
+ outflags |= MMAN_nl;
+}
+
static int
pre_vt(DECL_ARGS)
{
diff --git a/mdoc_term.c b/mdoc_term.c
index 0becd3b5..0307cca6 100644
--- a/mdoc_term.c
+++ b/mdoc_term.c
@@ -261,7 +261,9 @@ terminal_mdoc(void *arg, const struct roff_man *mdoc)
p = (struct termp *)arg;
p->overstep = 0;
p->rmargin = p->maxrmargin = p->defrmargin;
- p->tabwidth = term_len(p, 5);
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, ".5i");
n = mdoc->first->child;
if (p->synopsisonly) {
@@ -1128,8 +1130,14 @@ static void
termp_bl_post(DECL_ARGS)
{
- if (n->type == ROFFT_BLOCK)
- term_newln(p);
+ if (n->type != ROFFT_BLOCK)
+ return;
+ term_newln(p);
+ if (n->tok != MDOC_Bl || n->norm->Bl.type != LIST_column)
+ return;
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, ".5i");
}
static int
@@ -1272,6 +1280,9 @@ termp_sh_pre(DECL_ARGS)
break;
case ROFFT_BODY:
p->offset = term_len(p, p->defindent);
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, ".5i");
switch (n->sec) {
case SEC_DESCRIPTION:
fn_prio = 0;
@@ -1322,6 +1333,9 @@ termp_d1_pre(DECL_ARGS)
return 1;
term_newln(p);
p->offset += term_len(p, p->defindent + 1);
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, ".5i");
return 1;
}
@@ -1427,7 +1441,7 @@ termp_fa_pre(DECL_ARGS)
static int
termp_bd_pre(DECL_ARGS)
{
- size_t tabwidth, lm, len, rm, rmax;
+ size_t lm, len, rm, rmax;
struct roff_node *nn;
int offset;
@@ -1467,9 +1481,11 @@ termp_bd_pre(DECL_ARGS)
DISP_centered != n->norm->Bd.type)
return 1;
- tabwidth = p->tabwidth;
- if (DISP_literal == n->norm->Bd.type)
- p->tabwidth = term_len(p, 8);
+ if (n->norm->Bd.type == DISP_literal) {
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, "8n");
+ }
lm = p->offset;
rm = p->rmargin;
@@ -1493,9 +1509,9 @@ termp_bd_pre(DECL_ARGS)
* notion of selective eoln whitespace is pretty dumb
* anyway, so don't sweat it.
*/
+ if (nn->tok < ROFF_MAX)
+ continue;
switch (nn->tok) {
- case ROFF_br:
- case ROFF_sp:
case MDOC_Sm:
case MDOC_Bl:
case MDOC_D1:
@@ -1513,7 +1529,6 @@ termp_bd_pre(DECL_ARGS)
p->flags |= TERMP_NOSPACE;
}
- p->tabwidth = tabwidth;
p->rmargin = rm;
p->maxrmargin = rmax;
return 0;
@@ -1584,6 +1599,9 @@ termp_ss_pre(DECL_ARGS)
break;
case ROFFT_BODY:
p->offset = term_len(p, p->defindent);
+ term_tab_set(p, NULL);
+ term_tab_set(p, "T");
+ term_tab_set(p, ".5i");
break;
default:
break;
diff --git a/regress/roff/Makefile b/regress/roff/Makefile
index 96474204..c97b99b1 100644
--- a/regress/roff/Makefile
+++ b/regress/roff/Makefile
@@ -1,7 +1,7 @@
# $OpenBSD: Makefile,v 1.20 2015/02/06 16:05:51 schwarze Exp $
SUBDIR = args cond esc scale string
-SUBDIR += br cc de ds ft ig it ll na nr ps rm sp tr
+SUBDIR += br cc de ds ft ig it ll na nr ps rm sp ta tr
.include "../Makefile.sub"
.include <bsd.subdir.mk>
diff --git a/regress/roff/ta/Makefile b/regress/roff/ta/Makefile
new file mode 100644
index 00000000..656c5174
--- /dev/null
+++ b/regress/roff/ta/Makefile
@@ -0,0 +1,5 @@
+# $OpenBSD$
+
+REGRESS_TARGETS = basic-mdoc basic-man
+
+.include <bsd.regress.mk>
diff --git a/regress/roff/ta/basic-man.in b/regress/roff/ta/basic-man.in
new file mode 100644
index 00000000..f2f4641d
--- /dev/null
+++ b/regress/roff/ta/basic-man.in
@@ -0,0 +1,19 @@
+.TH TA-BASIC-MAN 1 "May 7, 2014" OpenBSD
+.SH NAME
+ta-basic-man \- setting tabstop positions in man(7)
+.SH DESCRIPTION
+.nf
+default:
+1 2 3
+10n:
+.ta 10n
+1 2 3
+none:
+.ta
+1 2 3
+3n +6n T 4n +2n:
+.ta 3n +6n T 4n +2n
+1 2 3 4 5 6 7 8 9
+default unit:
+.ta 3 +4 12
+1 2 3 4
diff --git a/regress/roff/ta/basic-man.out_ascii b/regress/roff/ta/basic-man.out_ascii
new file mode 100644
index 00000000..37062245
--- /dev/null
+++ b/regress/roff/ta/basic-man.out_ascii
@@ -0,0 +1,22 @@
+TA-BASIC-MAN(1) General Commands Manual TA-BASIC-MAN(1)
+
+
+
+NNAAMMEE
+ ta-basic-man - setting tabstop positions in man(7)
+
+DDEESSCCRRIIPPTTIIOONN
+ default:
+ 1 2 3
+ 10n:
+ 1 23
+ none:
+ 123
+ 3n +6n T 4n +2n:
+ 1 2 3 4 5 6 7 8 9
+ default unit:
+ 1 2 3 4
+
+
+
+OpenBSD May 7, 2014 TA-BASIC-MAN(1)
diff --git a/regress/roff/ta/basic-mdoc.in b/regress/roff/ta/basic-mdoc.in
new file mode 100644
index 00000000..24c83bd4
--- /dev/null
+++ b/regress/roff/ta/basic-mdoc.in
@@ -0,0 +1,34 @@
+.Dd May 7, 2017
+.Dt TA-BASIC-MDOC 1
+.Os OpenBSD
+.Sh NAME
+.Nm ta-basic-mdoc
+.Nd setting tabstop positions in mdoc(7)
+.Sh DESCRIPTION
+.Bd -unfilled
+default:
+1 2 3
+10n:
+.ta 10n
+1 2 3
+none:
+.ta
+1 2 3
+3n +6n T 4n +2n:
+.ta 3n +6n T 4n +2n
+1 2 3 4 5 6 7 8 9
+.Ed
+.Pp
+literal:
+.Bd -literal -compact
+1 2 3
+.Ed
+.Pp
+after literal:
+.br
+1 2 3
+.Pp
+default unit:
+.br
+.ta 3 +4 12
+1 2 3 4
diff --git a/regress/roff/ta/basic-mdoc.out_ascii b/regress/roff/ta/basic-mdoc.out_ascii
new file mode 100644
index 00000000..83feb627
--- /dev/null
+++ b/regress/roff/ta/basic-mdoc.out_ascii
@@ -0,0 +1,25 @@
+TA-BASIC-MDOC(1) General Commands Manual TA-BASIC-MDOC(1)
+
+NNAAMMEE
+ ttaa--bbaassiicc--mmddoocc - setting tabstop positions in mdoc(7)
+
+DDEESSCCRRIIPPTTIIOONN
+ default:
+ 1 2 3
+ 10n:
+ 1 23
+ none:
+ 123
+ 3n +6n T 4n +2n:
+ 1 2 3 4 5 6 7 8 9
+
+ literal:
+ 1 2 3
+
+ after literal:
+ 1 2 3
+
+ default unit:
+ 1 2 3 4
+
+OpenBSD May 7, 2017 OpenBSD
diff --git a/roff.c b/roff.c
index 1df5929e..6c387e5e 100644
--- a/roff.c
+++ b/roff.c
@@ -181,6 +181,7 @@ static enum rofferr roff_it(ROFF_ARGS);
static enum rofferr roff_line_ignore(ROFF_ARGS);
static void roff_man_alloc1(struct roff_man *);
static void roff_man_free1(struct roff_man *);
+static enum rofferr roff_manyarg(ROFF_ARGS);
static enum rofferr roff_nr(ROFF_ARGS);
static enum rofferr roff_onearg(ROFF_ARGS);
static enum roff_tok roff_parse(struct roff *, char *, int *,
@@ -212,7 +213,7 @@ static enum rofferr roff_userdef(ROFF_ARGS);
const char *__roff_name[MAN_MAX + 1] = {
"br", "ft", "ll", "sp",
- NULL,
+ "ta", NULL,
"ab", "ad", "af", "aln",
"als", "am", "am1", "ami",
"ami1", "as", "as1", "asciify",
@@ -262,7 +263,7 @@ const char *__roff_name[MAN_MAX + 1] = {
"shc", "shift", "sizes", "so",
"spacewidth", "special", "spreadwarn", "ss",
"sty", "substring", "sv", "sy",
- "T&", "ta", "tc", "TE",
+ "T&", "tc", "TE",
"TH", "ti", "tkf", "tl",
"tm", "tm1", "tmc", "tr",
"track", "transchar", "trf", "trimat",
@@ -322,6 +323,7 @@ static struct roffmac roffs[TOKEN_NONE] = {
{ roff_onearg, NULL, NULL, 0 }, /* ft */
{ roff_onearg, NULL, NULL, 0 }, /* ll */
{ roff_onearg, NULL, NULL, 0 }, /* sp */
+ { roff_manyarg, NULL, NULL, 0 }, /* ta */
{ NULL, NULL, NULL, 0 }, /* ROFF_MAX */
{ roff_unsupp, NULL, NULL, 0 }, /* ab */
{ roff_line_ignore, NULL, NULL, 0 }, /* ad */
@@ -520,7 +522,6 @@ static struct roffmac roffs[TOKEN_NONE] = {
{ roff_line_ignore, NULL, NULL, 0 }, /* sv */
{ roff_insec, NULL, NULL, 0 }, /* sy */
{ roff_T_, NULL, NULL, 0 }, /* T& */
- { roff_unsupp, NULL, NULL, 0 }, /* ta */
{ roff_unsupp, NULL, NULL, 0 }, /* tc */
{ roff_TE, NULL, NULL, 0 }, /* TE */
{ roff_TH, NULL, NULL, 0 }, /* TH */
@@ -2800,6 +2801,29 @@ roff_onearg(ROFF_ARGS)
}
static enum rofferr
+roff_manyarg(ROFF_ARGS)
+{
+ struct roff_node *n;
+ char *sp, *ep;
+
+ roff_elem_alloc(r->man, ln, ppos, tok);
+ n = r->man->last;
+
+ for (sp = ep = buf->buf + pos; *sp != '\0'; sp = ep) {
+ while (*ep != '\0' && *ep != ' ')
+ ep++;
+ while (*ep == ' ')
+ *ep++ = '\0';
+ roff_word_alloc(r->man, ln, sp - buf->buf, sp);
+ }
+
+ n->flags |= NODE_LINE | NODE_VALID | NODE_ENDED;
+ r->man->last = n;
+ r->man->next = ROFF_NEXT_SIBLING;
+ return ROFF_IGN;
+}
+
+static enum rofferr
roff_br(ROFF_ARGS)
{
roff_elem_alloc(r->man, ln, ppos, ROFF_br);
diff --git a/roff.h b/roff.h
index ba1ef8f2..ee701a75 100644
--- a/roff.h
+++ b/roff.h
@@ -70,6 +70,7 @@ enum roff_tok {
ROFF_ft,
ROFF_ll,
ROFF_sp,
+ ROFF_ta,
ROFF_MAX,
ROFF_ab,
ROFF_ad,
@@ -271,7 +272,6 @@ enum roff_tok {
ROFF_sv,
ROFF_sy,
ROFF_T_,
- ROFF_ta,
ROFF_tc,
ROFF_TE,
ROFF_TH,
diff --git a/roff_html.c b/roff_html.c
index 69e9ce54..5fd65d9f 100644
--- a/roff_html.c
+++ b/roff_html.c
@@ -36,6 +36,7 @@ static const roff_html_pre_fp roff_html_pre_acts[ROFF_MAX] = {
NULL, /* ft */
NULL, /* ll */
roff_html_pre_sp, /* sp */
+ NULL, /* ta */
};
diff --git a/roff_term.c b/roff_term.c
index ea34208e..9786e0a6 100644
--- a/roff_term.c
+++ b/roff_term.c
@@ -31,12 +31,14 @@ static void roff_term_pre_br(ROFF_TERM_ARGS);
static void roff_term_pre_ft(ROFF_TERM_ARGS);
static void roff_term_pre_ll(ROFF_TERM_ARGS);
static void roff_term_pre_sp(ROFF_TERM_ARGS);
+static void roff_term_pre_ta(ROFF_TERM_ARGS);
static const roff_term_pre_fp roff_term_pre_acts[ROFF_MAX] = {
roff_term_pre_br, /* br */
roff_term_pre_ft, /* ft */
roff_term_pre_ll, /* ft */
- roff_term_pre_sp, /* br */
+ roff_term_pre_sp, /* sp */
+ roff_term_pre_ta, /* ta */
};
@@ -111,3 +113,11 @@ roff_term_pre_sp(ROFF_TERM_ARGS)
roff_term_pre_br(p, n);
}
+
+static void
+roff_term_pre_ta(ROFF_TERM_ARGS)
+{
+ term_tab_set(p, NULL);
+ for (n = n->child; n != NULL; n = n->next)
+ term_tab_set(p, n->string);
+}
diff --git a/roff_validate.c b/roff_validate.c
index e18f3c1a..05df6cb6 100644
--- a/roff_validate.c
+++ b/roff_validate.c
@@ -35,6 +35,7 @@ static const roff_valid_fp roff_valids[ROFF_MAX] = {
roff_valid_ft, /* ft */
NULL, /* ll */
NULL, /* sp */
+ NULL, /* ta */
};
diff --git a/term.c b/term.c
index 28a26951..e52ba40c 100644
--- a/term.c
+++ b/term.c
@@ -141,8 +141,8 @@ term_flushln(struct termp *p)
* subsequent tabs into a single huge set of spaces.
*/
ntab = 0;
- while (i < p->col && '\t' == p->buf[i]) {
- vend = (vis / p->tabwidth + 1) * p->tabwidth;
+ while (i < p->col && p->buf[i] == '\t') {
+ vend = term_tab_next(vis);
vbl += vend - vis;
vis = vend;
ntab++;
@@ -192,17 +192,20 @@ term_flushln(struct termp *p)
vend -= vis;
(*p->endline)(p);
p->viscol = 0;
- if (TERMP_BRIND & p->flags) {
- vbl = p->rmargin;
- vend += p->rmargin;
- vend -= p->offset;
- } else
- vbl = p->offset;
- /* use pending tabs on the new line */
+ /* Use pending tabs on the new line. */
+
+ vbl = 0;
+ while (ntab--)
+ vbl = term_tab_next(vbl);
- if (0 < ntab)
- vbl += ntab * p->tabwidth;
+ /* Re-establish indentation. */
+
+ if (p->flags & TERMP_BRIND) {
+ vbl += p->rmargin;
+ vend += p->rmargin - p->offset;
+ } else
+ vbl += p->offset;
/*
* Remove the p->overstep width.
diff --git a/term.h b/term.h
index b2fbe5b8..f7f54428 100644
--- a/term.h
+++ b/term.h
@@ -64,7 +64,6 @@ struct termp {
size_t maxrmargin; /* Max right margin. */
size_t maxcols; /* Max size of buf. */
size_t offset; /* Margin offest. */
- size_t tabwidth; /* Distance of tab positions. */
size_t col; /* Bytes in buf. */
size_t viscol; /* Chars on current line. */
size_t trailspace; /* See termp_flushln(). */
@@ -130,6 +129,9 @@ int term_vspan(const struct termp *, const struct roffsu *);
size_t term_strlen(const struct termp *, const char *);
size_t term_len(const struct termp *, size_t);
+void term_tab_set(const struct termp *, const char *);
+size_t term_tab_next(size_t);
+
void term_fontpush(struct termp *, enum termfont);
void term_fontpop(struct termp *);
void term_fontpopq(struct termp *, int);
diff --git a/term_ascii.c b/term_ascii.c
index ee05c09f..1007ed28 100644
--- a/term_ascii.c
+++ b/term_ascii.c
@@ -68,7 +68,6 @@ ascii_init(enum termenc enc, const struct manoutput *outopts)
p = mandoc_calloc(1, sizeof(struct termp));
p->line = 1;
- p->tabwidth = 5;
p->defrmargin = p->lastrmargin = 78;
p->fontq = mandoc_reallocarray(NULL,
(p->fontsz = 8), sizeof(enum termfont));
diff --git a/term_tab.c b/term_tab.c
new file mode 100644
index 00000000..3e6fa5c1
--- /dev/null
+++ b/term_tab.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: term.c,v 1.119 2017/01/08 18:08:44 schwarze Exp $ */
+/*
+ * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#include <sys/types.h>
+
+#include <stddef.h>
+
+#include "mandoc_aux.h"
+#include "out.h"
+#include "term.h"
+
+struct tablist {
+ size_t *t; /* Allocated array of tab positions. */
+ size_t s; /* Allocated number of positions. */
+ size_t n; /* Currently used number of positions. */
+};
+
+static struct {
+ struct tablist a; /* All tab positions for lookup. */
+ struct tablist p; /* Periodic tab positions to add. */
+ size_t d; /* Default tab width in units of n. */
+} tabs;
+
+
+void
+term_tab_set(const struct termp *p, const char *arg)
+{
+ static int recording_period;
+
+ struct roffsu su;
+ struct tablist *tl;
+ size_t pos;
+ int add;
+
+ /* Special arguments: clear all tabs or switch lists. */
+
+ if (arg == NULL) {
+ tabs.a.n = tabs.p.n = 0;
+ recording_period = 0;
+ if (tabs.d == 0) {
+ a2roffsu(".8i", &su, SCALE_IN);
+ tabs.d = term_hspan(p, &su) / 24;
+ }
+ return;
+ }
+ if (arg[0] == 'T' && arg[1] == '\0') {
+ recording_period = 1;
+ return;
+ }
+
+ /* Parse the sign, the number, and the unit. */
+
+ if (*arg == '+') {
+ add = 1;
+ arg++;
+ } else
+ add = 0;
+ if (a2roffsu(arg, &su, SCALE_EM) == 0)
+ return;
+
+ /* Select the list, and extend it if it is full. */
+
+ tl = recording_period ? &tabs.p : &tabs.a;
+ if (tl->n >= tl->s) {
+ tl->s += 8;
+ tl->t = mandoc_reallocarray(tl->t, tl->s, sizeof(*tl->t));
+ }
+
+ /* Append the new position. */
+
+ pos = term_hspan(p, &su);
+ tl->t[tl->n] = pos;
+ if (add && tl->n)
+ tl->t[tl->n] += tl->t[tl->n - 1];
+ tl->n++;
+}
+
+size_t
+term_tab_next(size_t prev)
+{
+ size_t i, j;
+
+ for (i = 0;; i++) {
+ if (i == tabs.a.n) {
+ if (tabs.p.n == 0)
+ return prev;
+/*
+ return i ? prev :
+ (prev / tabs.d + 1) * tabs.d;
+ */
+ tabs.a.n += tabs.p.n;
+ if (tabs.a.s < tabs.a.n) {
+ tabs.a.s = tabs.a.n;
+ tabs.a.t = mandoc_reallocarray(tabs.a.t,
+ tabs.a.s, sizeof(*tabs.a.t));
+ }
+ for (j = 0; j < tabs.p.n; j++)
+ tabs.a.t[i + j] = tabs.p.t[j] +
+ (i ? tabs.a.t[i - 1] : 0);
+ }
+ if (prev < tabs.a.t[i] / 24)
+ return tabs.a.t[i] / 24;
+ }
+}