diff options
Diffstat (limited to 'contrib/mandoc/mdoc_term.c')
-rw-r--r-- | contrib/mandoc/mdoc_term.c | 122 |
1 files changed, 68 insertions, 54 deletions
diff --git a/contrib/mandoc/mdoc_term.c b/contrib/mandoc/mdoc_term.c index 931bc384a002..b0544de0304e 100644 --- a/contrib/mandoc/mdoc_term.c +++ b/contrib/mandoc/mdoc_term.c @@ -1,6 +1,6 @@ -/* $Id: mdoc_term.c,v 1.383 2023/11/13 19:13:01 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.387 2025/07/27 15:27:28 schwarze Exp $ */ /* - * Copyright (c) 2010, 2012-2020, 2022 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010,2012-2020,2022,2025 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> * @@ -302,7 +302,7 @@ print_mdoc_node(DECL_ARGS) { const struct mdoc_term_act *act; struct termpair npair; - size_t offset, rmargin; + size_t offset, rmargin; /* In basic units. */ int chld; /* @@ -441,70 +441,62 @@ print_mdoc_node(DECL_ARGS) static void print_mdoc_foot(struct termp *p, const struct roff_meta *meta) { - size_t sz; + char *title; + size_t datelen, titlen; /* In basic units. */ - term_fontrepl(p, TERMFONT_NONE); - - /* - * Output the footer in new-groff style, that is, three columns - * with the middle being the manual date and flanking columns - * being the operating system: - * - * SYSTEM DATE SYSTEM - */ + assert(meta->title != NULL); + datelen = term_strlen(p, meta->date); + if (meta->msec == NULL) + title = mandoc_strdup(meta->title); + else + mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec); + titlen = term_strlen(p, title); + term_fontrepl(p, TERMFONT_NONE); term_vspace(p); + /* Bottom left corner: operating system. */ + p->tcol->offset = 0; - sz = term_strlen(p, meta->date); - p->tcol->rmargin = p->maxrmargin > sz ? - (p->maxrmargin + term_len(p, 1) - sz) / 2 : 0; + p->tcol->rmargin = p->maxrmargin > datelen ? + (p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0; p->trailspace = 1; p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; term_word(p, meta->os); term_flushln(p); + /* At the bottom in the middle: manual date. */ + p->tcol->offset = p->tcol->rmargin; - sz = term_strlen(p, meta->os); - p->tcol->rmargin = p->maxrmargin > sz ? p->maxrmargin - sz : 0; + p->tcol->rmargin = p->maxrmargin > titlen ? + p->maxrmargin - titlen : 0; p->flags |= TERMP_NOSPACE; term_word(p, meta->date); term_flushln(p); + /* Bottom right corner: manual title and section. */ + p->tcol->offset = p->tcol->rmargin; p->tcol->rmargin = p->maxrmargin; p->trailspace = 0; p->flags &= ~TERMP_NOBREAK; p->flags |= TERMP_NOSPACE; - term_word(p, meta->os); + term_word(p, title); term_flushln(p); p->tcol->offset = 0; - p->tcol->rmargin = p->maxrmargin; p->flags = 0; + free(title); } static void print_mdoc_head(struct termp *p, const struct roff_meta *meta) { char *volume, *title; - size_t vollen, titlen; - - /* - * The header is strange. It has three components, which are - * really two with the first duplicated. It goes like this: - * - * IDENTIFIER TITLE IDENTIFIER - * - * The IDENTIFIER is NAME(SECTION), which is the command-name - * (if given, or "unknown" if not) followed by the manual page - * section. These are given in `Dt'. The TITLE is a free-form - * string depending on the manual volume. If not specified, it - * switches on the manual section. - */ + size_t vollen, titlen; /* In basic units. */ assert(meta->vol); if (NULL == meta->arch) @@ -514,6 +506,8 @@ print_mdoc_head(struct termp *p, const struct roff_meta *meta) meta->vol, meta->arch); vollen = term_strlen(p, volume); + /* Top left corner: manual title and section. */ + if (NULL == meta->msec) title = mandoc_strdup(meta->title); else @@ -524,13 +518,16 @@ print_mdoc_head(struct termp *p, const struct roff_meta *meta) p->flags |= TERMP_NOBREAK | TERMP_NOSPACE; p->trailspace = 1; p->tcol->offset = 0; - p->tcol->rmargin = 2 * (titlen+1) + vollen < p->maxrmargin ? + p->tcol->rmargin = + titlen * 2 + term_len(p, 2) + vollen < p->maxrmargin ? (p->maxrmargin - vollen + term_len(p, 1)) / 2 : - vollen < p->maxrmargin ? p->maxrmargin - vollen : 0; + vollen < p->maxrmargin ? p->maxrmargin - vollen : 0; term_word(p, title); term_flushln(p); + /* At the top in the middle: manual volume. */ + p->flags |= TERMP_NOSPACE; p->tcol->offset = p->tcol->rmargin; p->tcol->rmargin = p->tcol->offset + vollen + titlen < @@ -539,6 +536,8 @@ print_mdoc_head(struct termp *p, const struct roff_meta *meta) term_word(p, volume); term_flushln(p); + /* Top right corner: title and section, again. */ + p->flags &= ~TERMP_NOBREAK; p->trailspace = 0; if (p->tcol->rmargin + titlen <= p->maxrmargin) { @@ -556,6 +555,11 @@ print_mdoc_head(struct termp *p, const struct roff_meta *meta) free(volume); } +/* + * Interpret the string v as a scaled width or, if the syntax is invalid, + * measure how much width it takes up when printed. In both cases, + * return the width in basic units. + */ static int a2width(const struct termp *p, const char *v) { @@ -564,10 +568,10 @@ a2width(const struct termp *p, const char *v) end = a2roffsu(v, &su, SCALE_MAX); if (end == NULL || *end != '\0') { - su.unit = SCALE_EN; - su.scale = term_strlen(p, v) / term_strlen(p, "0"); + su.unit = SCALE_BU; + su.scale = term_strlen(p, v); } - return term_hen(p, &su); + return term_hspan(p, &su); } /* @@ -623,8 +627,11 @@ termp_it_pre(DECL_ARGS) struct roffsu su; char buf[24]; const struct roff_node *bl, *nn; - size_t ncols, dcol; - int i, offset, width; + size_t ncols; /* Number of columns in .Bl -column. */ + size_t dcol; /* Column spacing in basic units. */ + int i; /* Zero-based column index. */ + int offset; /* Start of column in basic units. */ + int width; /* Column width in basic units. */ enum mdoc_list type; if (n->type == ROFFT_BLOCK) { @@ -701,10 +708,9 @@ termp_it_pre(DECL_ARGS) for (i = 0, nn = n->prev; nn->prev && i < (int)ncols; nn = nn->prev, i++) { - su.unit = SCALE_EN; - su.scale = term_strlen(p, bl->norm->Bl.cols[i]) / - term_strlen(p, "0"); - offset += term_hen(p, &su) + dcol; + su.unit = SCALE_BU; + su.scale = term_strlen(p, bl->norm->Bl.cols[i]); + offset += term_hspan(p, &su) + dcol; } /* @@ -720,10 +726,9 @@ termp_it_pre(DECL_ARGS) * Use the declared column widths, extended as explained * in the preceding paragraph. */ - su.unit = SCALE_EN; - su.scale = term_strlen(p, bl->norm->Bl.cols[i]) / - term_strlen(p, "0"); - width = term_hen(p, &su) + dcol; + su.unit = SCALE_BU; + su.scale = term_strlen(p, bl->norm->Bl.cols[i]); + width = term_hspan(p, &su) + dcol; break; default: if (NULL == bl->norm->Bl.width) @@ -1274,6 +1279,7 @@ termp_sh_pre(DECL_ARGS) term_vspace(p); break; case ROFFT_HEAD: + p->fontibi = 1; return termp_bold_pre(p, pair, meta, n); case ROFFT_BODY: p->tcol->offset = term_len(p, p->defindent); @@ -1294,6 +1300,7 @@ termp_sh_post(DECL_ARGS) { switch (n->type) { case ROFFT_HEAD: + p->fontibi = 0; term_newln(p); break; case ROFFT_BODY: @@ -1421,7 +1428,7 @@ termp_fa_pre(DECL_ARGS) static int termp_bd_pre(DECL_ARGS) { - int offset; + int offset; /* In basic units. */ if (n->type == ROFFT_BLOCK) { print_bvspace(p, n, n); @@ -1509,7 +1516,8 @@ termp_ss_pre(DECL_ARGS) term_vspace(p); break; case ROFFT_HEAD: - p->tcol->offset = term_len(p, (p->defindent+1)/2); + p->tcol->offset = term_len(p, p->defindent) / 2 + 1; + p->fontibi = 1; return termp_bold_pre(p, pair, meta, n); case ROFFT_BODY: p->tcol->offset = term_len(p, p->defindent); @@ -1526,8 +1534,16 @@ termp_ss_pre(DECL_ARGS) static void termp_ss_post(DECL_ARGS) { - if (n->type == ROFFT_HEAD || n->type == ROFFT_BODY) + switch (n->type) { + case ROFFT_HEAD: + p->fontibi = 0; + /* FALLTHROUGH */ + case ROFFT_BODY: term_newln(p); + break; + default: + break; + } } static int @@ -1888,9 +1904,7 @@ termp_lk_pre(DECL_ARGS) } /* Link target. */ - term_fontpush(p, TERMFONT_BOLD); term_word(p, link->string); - term_fontpop(p); /* Trailing punctuation. */ while (punct != NULL) { |