summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/mandoc/Makefile4
-rw-r--r--usr.bin/mandoc/man_term.c6
-rw-r--r--usr.bin/mandoc/mdoc_man.c14
-rw-r--r--usr.bin/mandoc/mdoc_term.c40
-rw-r--r--usr.bin/mandoc/roff.c32
-rw-r--r--usr.bin/mandoc/roff.h4
-rw-r--r--usr.bin/mandoc/roff_html.c3
-rw-r--r--usr.bin/mandoc/roff_term.c14
-rw-r--r--usr.bin/mandoc/roff_validate.c3
-rw-r--r--usr.bin/mandoc/term.c27
-rw-r--r--usr.bin/mandoc/term.h6
-rw-r--r--usr.bin/mandoc/term_ascii.c3
-rw-r--r--usr.bin/mandoc/term_tab.c117
13 files changed, 230 insertions, 43 deletions
diff --git a/usr.bin/mandoc/Makefile b/usr.bin/mandoc/Makefile
index 2602ee65e46..6e01f65a74b 100644
--- a/usr.bin/mandoc/Makefile
+++ b/usr.bin/mandoc/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.108 2017/05/05 02:06:17 schwarze Exp $
+# $OpenBSD: Makefile,v 1.109 2017/05/07 17:30:58 schwarze Exp $
.include <bsd.own.mk>
@@ -12,7 +12,7 @@ SRCS+= mdoc_macro.c mdoc.c \
mdoc_argv.c mdoc_state.c mdoc_validate.c att.c msec.c st.c
SRCS+= man_macro.c man.c man_validate.c
SRCS+= main.c out.c tag.c tree.c
-SRCS+= term.c term_ascii.c term_ps.c
+SRCS+= term.c term_tab.c term_ascii.c term_ps.c
SRCS+= roff_term.c mdoc_term.c man_term.c eqn_term.c tbl_term.c
SRCS+= mdoc_man.c
SRCS+= html.c roff_html.c mdoc_html.c man_html.c eqn_html.c tbl_html.c
diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c
index 4c7d332b6a3..64ce13ed70d 100644
--- a/usr.bin/mandoc/man_term.c
+++ b/usr.bin/mandoc/man_term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: man_term.c,v 1.150 2017/05/05 15:16:25 schwarze Exp $ */
+/* $OpenBSD: man_term.c,v 1.151 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -140,7 +140,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/usr.bin/mandoc/mdoc_man.c b/usr.bin/mandoc/mdoc_man.c
index b8bc11bff4d..f20d39c82e4 100644
--- a/usr.bin/mandoc/mdoc_man.c
+++ b/usr.bin/mandoc/mdoc_man.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mdoc_man.c,v 1.111 2017/05/05 15:16:25 schwarze Exp $ */
+/* $OpenBSD: mdoc_man.c,v 1.112 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2011-2017 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -110,6 +110,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 *);
@@ -126,6 +127,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] = {
@@ -441,7 +443,6 @@ static void
print_line(const char *s, int newflags)
{
- outflags &= ~MMAN_br;
outflags |= MMAN_nl;
print_word(s);
outflags |= newflags;
@@ -1713,6 +1714,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/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c
index c9c430d90b9..6369966b917 100644
--- a/usr.bin/mandoc/mdoc_term.c
+++ b/usr.bin/mandoc/mdoc_term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mdoc_term.c,v 1.254 2017/05/05 15:16:25 schwarze Exp $ */
+/* $OpenBSD: mdoc_term.c,v 1.255 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -259,7 +259,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) {
@@ -1126,8 +1128,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
@@ -1270,6 +1278,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;
@@ -1320,6 +1331,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;
}
@@ -1425,7 +1439,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;
@@ -1465,9 +1479,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;
@@ -1491,9 +1507,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:
@@ -1511,7 +1527,6 @@ termp_bd_pre(DECL_ARGS)
p->flags |= TERMP_NOSPACE;
}
- p->tabwidth = tabwidth;
p->rmargin = rm;
p->maxrmargin = rmax;
return 0;
@@ -1582,6 +1597,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/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c
index 3e7dd5ab390..3448c46da18 100644
--- a/usr.bin/mandoc/roff.c
+++ b/usr.bin/mandoc/roff.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff.c,v 1.171 2017/05/05 15:16:25 schwarze Exp $ */
+/* $OpenBSD: roff.c,v 1.172 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -179,6 +179,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 *,
@@ -210,7 +211,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",
@@ -260,7 +261,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",
@@ -320,6 +321,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 */
@@ -518,7 +520,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 */
@@ -2798,6 +2799,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/usr.bin/mandoc/roff.h b/usr.bin/mandoc/roff.h
index 063fff05573..61c72bf4baa 100644
--- a/usr.bin/mandoc/roff.h
+++ b/usr.bin/mandoc/roff.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff.h,v 1.28 2017/05/05 15:16:26 schwarze Exp $ */
+/* $OpenBSD: roff.h,v 1.29 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -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/usr.bin/mandoc/roff_html.c b/usr.bin/mandoc/roff_html.c
index c17b155155c..7778d94c433 100644
--- a/usr.bin/mandoc/roff_html.c
+++ b/usr.bin/mandoc/roff_html.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff_html.c,v 1.3 2017/05/05 15:16:26 schwarze Exp $ */
+/* $OpenBSD: roff_html.c,v 1.4 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -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/usr.bin/mandoc/roff_term.c b/usr.bin/mandoc/roff_term.c
index c58ea1ffc41..770fed68e6b 100644
--- a/usr.bin/mandoc/roff_term.c
+++ b/usr.bin/mandoc/roff_term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff_term.c,v 1.4 2017/05/05 15:16:26 schwarze Exp $ */
+/* $OpenBSD: roff_term.c,v 1.5 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2010, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -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/usr.bin/mandoc/roff_validate.c b/usr.bin/mandoc/roff_validate.c
index 11ce9e19c2e..154b66a90e9 100644
--- a/usr.bin/mandoc/roff_validate.c
+++ b/usr.bin/mandoc/roff_validate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: roff_validate.c,v 1.3 2017/05/05 15:16:26 schwarze Exp $ */
+/* $OpenBSD: roff_validate.c,v 1.4 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2010, 2017 Ingo Schwarze <schwarze@openbsd.org>
*
@@ -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/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c
index aa36e557bd0..2a4a44f41fa 100644
--- a/usr.bin/mandoc/term.c
+++ b/usr.bin/mandoc/term.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: term.c,v 1.119 2017/01/08 18:08:44 schwarze Exp $ */
+/* $OpenBSD: term.c,v 1.120 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -139,8 +139,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++;
@@ -190,17 +190,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/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h
index 4b688de65d5..f2bcca05902 100644
--- a/usr.bin/mandoc/term.h
+++ b/usr.bin/mandoc/term.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: term.h,v 1.63 2017/05/04 22:07:44 schwarze Exp $ */
+/* $OpenBSD: term.h,v 1.64 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -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/usr.bin/mandoc/term_ascii.c b/usr.bin/mandoc/term_ascii.c
index e2e3c251416..6700c2ec3f3 100644
--- a/usr.bin/mandoc/term_ascii.c
+++ b/usr.bin/mandoc/term_ascii.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: term_ascii.c,v 1.39 2016/07/08 22:27:58 schwarze Exp $ */
+/* $OpenBSD: term_ascii.c,v 1.40 2017/05/07 17:30:58 schwarze Exp $ */
/*
* Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -58,7 +58,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/usr.bin/mandoc/term_tab.c b/usr.bin/mandoc/term_tab.c
new file mode 100644
index 00000000000..9d9e7812a7e
--- /dev/null
+++ b/usr.bin/mandoc/term_tab.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: term_tab.c,v 1.1 2017/05/07 17:30:58 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;
+ }
+}