diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makefile.depend | 1 | ||||
-rw-r--r-- | man_term.c | 4 | ||||
-rw-r--r-- | mdoc_man.c | 12 | ||||
-rw-r--r-- | mdoc_term.c | 38 | ||||
-rw-r--r-- | regress/roff/Makefile | 2 | ||||
-rw-r--r-- | regress/roff/ta/Makefile | 5 | ||||
-rw-r--r-- | regress/roff/ta/basic-man.in | 19 | ||||
-rw-r--r-- | regress/roff/ta/basic-man.out_ascii | 22 | ||||
-rw-r--r-- | regress/roff/ta/basic-mdoc.in | 34 | ||||
-rw-r--r-- | regress/roff/ta/basic-mdoc.out_ascii | 25 | ||||
-rw-r--r-- | roff.c | 30 | ||||
-rw-r--r-- | roff.h | 2 | ||||
-rw-r--r-- | roff_html.c | 1 | ||||
-rw-r--r-- | roff_term.c | 12 | ||||
-rw-r--r-- | roff_validate.c | 1 | ||||
-rw-r--r-- | term.c | 25 | ||||
-rw-r--r-- | term.h | 4 | ||||
-rw-r--r-- | term_ascii.c | 1 | ||||
-rw-r--r-- | term_tab.c | 117 |
20 files changed, 326 insertions, 31 deletions
@@ -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 @@ -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); @@ -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 @@ -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); @@ -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 */ }; @@ -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. @@ -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; + } +} |