diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2017-06-04 22:44:15 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2017-06-04 22:44:15 +0000 |
commit | 57a85465cebb415008468ba9f16a7668e9119051 (patch) | |
tree | d342974ea656a6dfa44886c5469b783de62b7078 | |
parent | 68a2cb887c993621fe7b72e21517d6a260376003 (diff) | |
download | mandoc-57a85465cebb415008468ba9f16a7668e9119051.tar.gz |
Implement the roff(7) .mc (right margin character) request.
The Tcl/Tk manual pages use this extensively.
Delete the TERM_MAXMARGIN hack, it breaks .mc inside .nf;
instead, implement a proper TERMP_BRNEVER flag.
-rw-r--r-- | man_term.c | 17 | ||||
-rw-r--r-- | mdoc_man.c | 1 | ||||
-rw-r--r-- | mdoc_term.c | 30 | ||||
-rw-r--r-- | roff.7 | 4 | ||||
-rw-r--r-- | roff.c | 8 | ||||
-rw-r--r-- | roff.h | 2 | ||||
-rw-r--r-- | roff_html.c | 3 | ||||
-rw-r--r-- | roff_term.c | 21 | ||||
-rw-r--r-- | roff_validate.c | 3 | ||||
-rw-r--r-- | tbl_term.c | 25 | ||||
-rw-r--r-- | term.c | 99 | ||||
-rw-r--r-- | term.h | 7 |
12 files changed, 119 insertions, 101 deletions
@@ -862,7 +862,6 @@ post_UR(DECL_ARGS) static void print_man_node(DECL_ARGS) { - size_t rm, rmax; int c; switch (n->type) { @@ -930,20 +929,16 @@ out: if (mt->fl & MANT_LITERAL && ! (p->flags & (TERMP_NOBREAK | TERMP_NONEWLINE)) && (n->next == NULL || n->next->flags & NODE_LINE)) { - rm = p->rmargin; - rmax = p->maxrmargin; - p->rmargin = p->maxrmargin = TERM_MAXMARGIN; - p->flags |= TERMP_NOSPACE; + p->flags |= TERMP_BRNEVER | TERMP_NOSPACE; if (n->string != NULL && *n->string != '\0') term_flushln(p); else term_newln(p); - if (rm < rmax && n->parent->tok == MAN_HP) { - p->offset = rm; - p->rmargin = rmax; - } else - p->rmargin = rm; - p->maxrmargin = rmax; + p->flags &= ~TERMP_BRNEVER; + if (p->rmargin < p->maxrmargin && n->parent->tok == MAN_HP) { + p->offset = p->rmargin; + p->rmargin = p->maxrmargin; + } } if (NODE_EOS & n->flags) p->flags |= TERMP_SENTENCE; @@ -128,6 +128,7 @@ static const void_fp roff_manacts[ROFF_MAX] = { pre_br, pre_ft, pre_onearg, + pre_onearg, pre_sp, pre_ta, pre_onearg, diff --git a/mdoc_term.c b/mdoc_term.c index 26ddbea1..ed462d61 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -1413,7 +1413,7 @@ termp_fa_pre(DECL_ARGS) static int termp_bd_pre(DECL_ARGS) { - size_t lm, len, rm, rmax; + size_t lm, len; struct roff_node *nn; int offset; @@ -1460,17 +1460,14 @@ termp_bd_pre(DECL_ARGS) } lm = p->offset; - rm = p->rmargin; - rmax = p->maxrmargin; - p->rmargin = p->maxrmargin = TERM_MAXMARGIN; - + p->flags |= TERMP_BRNEVER; for (nn = n->child; nn; nn = nn->next) { if (DISP_centered == n->norm->Bd.type) { if (nn->type == ROFFT_TEXT) { len = term_strlen(p, nn->string); - p->offset = len >= rm ? 0 : - lm + len >= rm ? rm - len : - (lm + rm - len) / 2; + p->offset = len >= p->rmargin ? 0 : + lm + len >= p->rmargin ? p->rmargin - len : + (lm + p->rmargin - len) / 2; } else p->offset = lm; } @@ -1500,32 +1497,21 @@ termp_bd_pre(DECL_ARGS) term_flushln(p); p->flags |= TERMP_NOSPACE; } - - p->rmargin = rm; - p->maxrmargin = rmax; + p->flags &= ~TERMP_BRNEVER; return 0; } static void termp_bd_post(DECL_ARGS) { - size_t rm, rmax; - if (n->type != ROFFT_BODY) return; - - rm = p->rmargin; - rmax = p->maxrmargin; - if (DISP_literal == n->norm->Bd.type || DISP_unfilled == n->norm->Bd.type) - p->rmargin = p->maxrmargin = TERM_MAXMARGIN; - + p->flags |= TERMP_BRNEVER; p->flags |= TERMP_NOSPACE; term_newln(p); - - p->rmargin = rm; - p->maxrmargin = rmax; + p->flags &= ~TERMP_BRNEVER; } static int @@ -1296,7 +1296,9 @@ Set title line length. Currently ignored. .It Ic \&mc Ar glyph Op Ar dist Print margin character in the right margin. -Currently ignored. +The +.Ar dist +is currently ignored; instead, 1n is used. .It Ic \&mediasize Ar media Set the device media size. This is a Heirloom extension and currently ignored. @@ -215,8 +215,8 @@ static enum rofferr roff_userdef(ROFF_ARGS); #define ROFFNUM_WHITE (1 << 1) /* Skip whitespace in roff_evalnum(). */ const char *__roff_name[MAN_MAX + 1] = { - "br", "ft", "ll", "sp", - "ta", "ti", NULL, + "br", "ft", "ll", "mc", + "sp", "ta", "ti", NULL, "ab", "ad", "af", "aln", "als", "am", "am1", "ami", "ami1", "as", "as1", "asciify", @@ -249,7 +249,7 @@ const char *__roff_name[MAN_MAX + 1] = { "lc", "lc_ctype", "lds", "length", "letadj", "lf", "lg", "lhang", "linetabs", "lnr", "lnrf", "lpfx", - "ls", "lsm", "lt", "mc", + "ls", "lsm", "lt", "mediasize", "minss", "mk", "mso", "na", "ne", "nh", "nhychar", "nm", "nn", "nop", "nr", @@ -325,6 +325,7 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_br, NULL, NULL, 0 }, /* br */ { roff_onearg, NULL, NULL, 0 }, /* ft */ { roff_onearg, NULL, NULL, 0 }, /* ll */ + { roff_onearg, NULL, NULL, 0 }, /* mc */ { roff_onearg, NULL, NULL, 0 }, /* sp */ { roff_manyarg, NULL, NULL, 0 }, /* ta */ { roff_onearg, NULL, NULL, 0 }, /* ti */ @@ -460,7 +461,6 @@ static struct roffmac roffs[TOKEN_NONE] = { { roff_line_ignore, NULL, NULL, 0 }, /* ls */ { roff_unsupp, NULL, NULL, 0 }, /* lsm */ { roff_line_ignore, NULL, NULL, 0 }, /* lt */ - { roff_line_ignore, NULL, NULL, 0 }, /* mc */ { roff_line_ignore, NULL, NULL, 0 }, /* mediasize */ { roff_line_ignore, NULL, NULL, 0 }, /* minss */ { roff_line_ignore, NULL, NULL, 0 }, /* mk */ @@ -69,6 +69,7 @@ enum roff_tok { ROFF_br = 0, ROFF_ft, ROFF_ll, + ROFF_mc, ROFF_sp, ROFF_ta, ROFF_ti, @@ -206,7 +207,6 @@ enum roff_tok { ROFF_ls, ROFF_lsm, ROFF_lt, - ROFF_mc, ROFF_mediasize, ROFF_minss, ROFF_mk, diff --git a/roff_html.c b/roff_html.c index e76ca544..f04b93c5 100644 --- a/roff_html.c +++ b/roff_html.c @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org> @@ -35,6 +35,7 @@ static const roff_html_pre_fp roff_html_pre_acts[ROFF_MAX] = { roff_html_pre_br, /* br */ NULL, /* ft */ NULL, /* ll */ + NULL, /* mc */ roff_html_pre_sp, /* sp */ NULL, /* ta */ NULL, /* ti */ diff --git a/roff_term.c b/roff_term.c index 3c2f24a9..22af42b0 100644 --- a/roff_term.c +++ b/roff_term.c @@ -1,4 +1,4 @@ -/* $OpenBSD$ */ +/* $Id$ */ /* * Copyright (c) 2010, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org> * @@ -30,6 +30,7 @@ typedef void (*roff_term_pre_fp)(ROFF_TERM_ARGS); 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_mc(ROFF_TERM_ARGS); static void roff_term_pre_sp(ROFF_TERM_ARGS); static void roff_term_pre_ta(ROFF_TERM_ARGS); static void roff_term_pre_ti(ROFF_TERM_ARGS); @@ -37,7 +38,8 @@ static void roff_term_pre_ti(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_ll, /* ll */ + roff_term_pre_mc, /* mc */ roff_term_pre_sp, /* sp */ roff_term_pre_ta, /* ta */ roff_term_pre_ti, /* ti */ @@ -95,6 +97,21 @@ roff_term_pre_ll(ROFF_TERM_ARGS) } static void +roff_term_pre_mc(ROFF_TERM_ARGS) +{ + if (p->col) { + p->flags |= TERMP_NOBREAK; + term_flushln(p); + p->flags &= ~(TERMP_NOBREAK | TERMP_NOSPACE); + } + if (n->child != NULL) { + p->mc = n->child->string; + p->flags |= TERMP_NEWMC; + } else + p->flags |= TERMP_ENDMC; +} + +static void roff_term_pre_sp(ROFF_TERM_ARGS) { struct roffsu su; diff --git a/roff_validate.c b/roff_validate.c index e1ee0ea9..f62544ca 100644 --- a/roff_validate.c +++ b/roff_validate.c @@ -1,4 +1,4 @@ -/* $OpenBSD: roff_html.c,v 1.1 2017/05/04 22:07:44 schwarze Exp $ */ +/* $Id$ */ /* * Copyright (c) 2010, 2017 Ingo Schwarze <schwarze@openbsd.org> * @@ -34,6 +34,7 @@ static const roff_valid_fp roff_valids[ROFF_MAX] = { NULL, /* br */ roff_valid_ft, /* ft */ NULL, /* ll */ + NULL, /* mc */ NULL, /* sp */ NULL, /* ta */ NULL, /* ti */ @@ -1,7 +1,7 @@ /* $Id$ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2011, 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011,2012,2014,2015,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 @@ -63,18 +63,12 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) const struct tbl_cell *cp; const struct tbl_dat *dp; static size_t offset; - size_t rmargin, maxrmargin, tsz; + size_t tsz; int ic, horiz, spans, vert; - rmargin = tp->rmargin; - maxrmargin = tp->maxrmargin; - - tp->rmargin = tp->maxrmargin = TERM_MAXMARGIN; - /* Inhibit printing of spaces: we do padding ourselves. */ - tp->flags |= TERMP_NONOSPACE; - tp->flags |= TERMP_NOSPACE; + tp->flags |= TERMP_NOSPACE | TERMP_NONOSPACE | TERMP_BRNEVER; /* * The first time we're invoked for a given table block, @@ -86,7 +80,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) tp->tbl.slen = term_tbl_strlen; tp->tbl.arg = tp; - tblcalc(&tp->tbl, sp, rmargin - tp->offset); + tblcalc(&tp->tbl, sp, tp->rmargin - tp->offset); /* Center the table as a whole. */ @@ -97,10 +91,10 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) for (ic = 0; ic < sp->opts->cols; ic++) tsz += tp->tbl.cols[ic].width + 3; tsz -= 3; - if (offset + tsz > rmargin) + if (offset + tsz > tp->rmargin) tsz -= 1; - tp->offset = (offset + rmargin > tsz) ? - (offset + rmargin - tsz) / 2 : 0; + tp->offset = (offset + tp->rmargin > tsz) ? + (offset + tp->rmargin - tsz) / 2 : 0; } /* Horizontal frame at the start of boxed tables. */ @@ -201,10 +195,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp) tp->tbl.cols = NULL; tp->offset = offset; } - - tp->flags &= ~TERMP_NONOSPACE; - tp->rmargin = rmargin; - tp->maxrmargin = maxrmargin; + tp->flags &= ~(TERMP_NONOSPACE | TERMP_BRNEVER); } /* @@ -36,6 +36,7 @@ static void adjbuf(struct termp *p, size_t); static void bufferc(struct termp *, char); static void encode(struct termp *, const char *, size_t); static void encode1(struct termp *, int); +static void endline(struct termp *); void @@ -169,10 +170,10 @@ term_flushln(struct termp *p) * Find out whether we would exceed the right margin. * If so, break to the next line. */ - if (vend > bp && 0 == jhy && vis > 0) { + if (vend > bp && 0 == jhy && vis > 0 && + (p->flags & TERMP_BRNEVER) == 0) { vend -= vis; - (*p->endline)(p); - p->viscol = 0; + endline(p); /* Use pending tabs on the new line. */ @@ -243,31 +244,37 @@ term_flushln(struct termp *p) vis = 0; p->col = 0; + p->minbl = p->trailspace; p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE | TERMP_NOPAD); - if ( ! (TERMP_NOBREAK & p->flags)) { - p->viscol = 0; - p->minbl = 0; - (*p->endline)(p); - return; - } - - if (TERMP_HANG & p->flags) { - p->minbl = p->trailspace; - return; - } - /* Trailing whitespace is significant in some columns. */ if (vis && vbl && (TERMP_BRTRSP & p->flags)) vis += vbl; /* If the column was overrun, break the line. */ - if (maxvis < vis + p->trailspace * (*p->width)(p, ' ')) { - (*p->endline)(p); - p->viscol = 0; - p->minbl = 0; - } else - p->minbl = p->trailspace; + if ((p->flags & TERMP_NOBREAK) == 0 || + ((p->flags & TERMP_HANG) == 0 && + vis + p->trailspace * (*p->width)(p, ' ') > maxvis)) + endline(p); +} + +static void +endline(struct termp *p) +{ + if ((p->flags & (TERMP_NEWMC | TERMP_ENDMC)) == TERMP_ENDMC) { + p->mc = NULL; + p->flags &= ~TERMP_ENDMC; + } + if (p->mc != NULL) { + if (p->viscol && p->maxrmargin >= p->viscol) + (*p->advance)(p, p->maxrmargin - p->viscol + 1); + p->flags |= TERMP_NOBUF | TERMP_NOSPACE; + term_word(p, p->mc); + p->flags &= ~(TERMP_NOBUF | TERMP_NEWMC); + } + p->viscol = 0; + p->minbl = 0; + (*p->endline)(p); } /* @@ -296,6 +303,7 @@ term_vspace(struct termp *p) term_newln(p); p->viscol = 0; + p->minbl = 0; if (0 < p->skipvsp) p->skipvsp--; else @@ -370,24 +378,24 @@ term_word(struct termp *p, const char *word) size_t csz, lsz, ssz; enum mandoc_esc esc; - if ( ! (TERMP_NOSPACE & p->flags)) { - if ( ! (TERMP_KEEP & p->flags)) { - bufferc(p, ' '); - if (TERMP_SENTENCE & p->flags) + if ((p->flags & TERMP_NOBUF) == 0) { + if ((p->flags & TERMP_NOSPACE) == 0) { + if ((p->flags & TERMP_KEEP) == 0) { bufferc(p, ' '); - } else - bufferc(p, ASCII_NBRSP); + if (p->flags & TERMP_SENTENCE) + bufferc(p, ' '); + } else + bufferc(p, ASCII_NBRSP); + } + if (p->flags & TERMP_PREKEEP) + p->flags |= TERMP_KEEP; + if (p->flags & TERMP_NONOSPACE) + p->flags |= TERMP_NOSPACE; + else + p->flags &= ~TERMP_NOSPACE; + p->flags &= ~(TERMP_SENTENCE | TERMP_NONEWLINE); + p->skipvsp = 0; } - if (TERMP_PREKEEP & p->flags) - p->flags |= TERMP_KEEP; - - if ( ! (p->flags & TERMP_NONOSPACE)) - p->flags &= ~TERMP_NOSPACE; - else - p->flags |= TERMP_NOSPACE; - - p->flags &= ~(TERMP_SENTENCE | TERMP_NONEWLINE); - p->skipvsp = 0; while ('\0' != *word) { if ('\\' != *word) { @@ -590,10 +598,12 @@ adjbuf(struct termp *p, size_t sz) static void bufferc(struct termp *p, char c) { - + if (p->flags & TERMP_NOBUF) { + (*p->letter)(p, c); + return; + } if (p->col + 1 >= p->maxcols) adjbuf(p, p->col + 1); - p->buf[p->col++] = c; } @@ -607,6 +617,11 @@ encode1(struct termp *p, int c) { enum termfont f; + if (p->flags & TERMP_NOBUF) { + (*p->letter)(p, c); + return; + } + if (p->col + 7 >= p->maxcols) adjbuf(p, p->col + 7); @@ -643,6 +658,12 @@ encode(struct termp *p, const char *word, size_t sz) { size_t i; + if (p->flags & TERMP_NOBUF) { + for (i = 0; i < sz; i++) + (*p->letter)(p, word[i]); + return; + } + if (p->col + 2 + (sz * 5) >= p->maxcols) adjbuf(p, p->col + 2 + (sz * 5)); @@ -36,8 +36,6 @@ enum termfont { TERMFONT__MAX }; -#define TERM_MAXMARGIN 100000 /* FIXME */ - struct eqn; struct roff_meta; struct roff_node; @@ -87,6 +85,10 @@ struct termp { #define TERMP_NOSPLIT (1 << 13) /* Do not break line before .An. */ #define TERMP_SPLIT (1 << 14) /* Break line before .An. */ #define TERMP_NONEWLINE (1 << 15) /* No line break in nofill mode. */ +#define TERMP_BRNEVER (1 << 16) /* Don't even break at maxrmargin. */ +#define TERMP_NOBUF (1 << 17) /* Bypass output buffer. */ +#define TERMP_NEWMC (1 << 18) /* No .mc printed yet. */ +#define TERMP_ENDMC (1 << 19) /* Next break ends .mc mode. */ int *buf; /* Output buffer. */ enum termenc enc; /* Type of encoding. */ enum termfont fontl; /* Last font set. */ @@ -105,6 +107,7 @@ struct termp { int (*hspan)(const struct termp *, const struct roffsu *); const void *argf; /* arg for headf/footf */ + const char *mc; /* Margin character. */ struct termp_ps *ps; }; |