summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2017-06-04 22:44:15 +0000
committerIngo Schwarze <schwarze@openbsd.org>2017-06-04 22:44:15 +0000
commit57a85465cebb415008468ba9f16a7668e9119051 (patch)
treed342974ea656a6dfa44886c5469b783de62b7078
parent68a2cb887c993621fe7b72e21517d6a260376003 (diff)
downloadmandoc-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.c17
-rw-r--r--mdoc_man.c1
-rw-r--r--mdoc_term.c30
-rw-r--r--roff.74
-rw-r--r--roff.c8
-rw-r--r--roff.h2
-rw-r--r--roff_html.c3
-rw-r--r--roff_term.c21
-rw-r--r--roff_validate.c3
-rw-r--r--tbl_term.c25
-rw-r--r--term.c99
-rw-r--r--term.h7
12 files changed, 119 insertions, 101 deletions
diff --git a/man_term.c b/man_term.c
index b86af98f..8a047d8b 100644
--- a/man_term.c
+++ b/man_term.c
@@ -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;
diff --git a/mdoc_man.c b/mdoc_man.c
index 3bd059c0..26293214 100644
--- a/mdoc_man.c
+++ b/mdoc_man.c
@@ -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
diff --git a/roff.7 b/roff.7
index 86d6cb84..b2e8fb78 100644
--- a/roff.7
+++ b/roff.7
@@ -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.
diff --git a/roff.c b/roff.c
index 83376e90..de3e204c 100644
--- a/roff.c
+++ b/roff.c
@@ -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 */
diff --git a/roff.h b/roff.h
index 4fd0fa42..3823490a 100644
--- a/roff.h
+++ b/roff.h
@@ -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 */
diff --git a/tbl_term.c b/tbl_term.c
index ef64a838..c436481b 100644
--- a/tbl_term.c
+++ b/tbl_term.c
@@ -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);
}
/*
diff --git a/term.c b/term.c
index 0c0fef67..b9bdc9b9 100644
--- a/term.c
+++ b/term.c
@@ -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));
diff --git a/term.h b/term.h
index 58def3a1..a4dbdf42 100644
--- a/term.h
+++ b/term.h
@@ -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;
};