summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--html.c33
-rw-r--r--mandoc.c2
-rw-r--r--mandoc.h1
-rw-r--r--mdoc_markdown.c13
-rw-r--r--regress/roff/esc/Makefile2
-rw-r--r--regress/roff/esc/p.in15
-rw-r--r--regress/roff/esc/p.out_ascii19
-rw-r--r--roff.72
-rw-r--r--term.c32
9 files changed, 110 insertions, 9 deletions
diff --git a/html.c b/html.c
index 2ff1d84c..c7037ad0 100644
--- a/html.c
+++ b/html.c
@@ -345,16 +345,18 @@ static int
print_encode(struct html *h, const char *p, const char *pend, int norecurse)
{
char numbuf[16];
- size_t sz;
- int c, len, nospace;
+ struct tag *t;
const char *seq;
+ size_t sz;
+ int c, len, breakline, nospace;
enum mandoc_esc esc;
- static const char rejs[9] = { '\\', '<', '>', '&', '"',
+ static const char rejs[10] = { ' ', '\\', '<', '>', '&', '"',
ASCII_NBRSP, ASCII_HYPH, ASCII_BREAK, '\0' };
if (pend == NULL)
pend = strchr(p, '\0');
+ breakline = 0;
nospace = 0;
while (p < pend) {
@@ -365,14 +367,28 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
}
for (sz = strcspn(p, rejs); sz-- && p < pend; p++)
- if (*p == ' ')
- print_endword(h);
- else
- print_byte(h, *p);
+ print_byte(h, *p);
+
+ if (breakline &&
+ (p >= pend || *p == ' ' || *p == ASCII_NBRSP)) {
+ t = print_otag(h, TAG_DIV, "");
+ print_text(h, "\\~");
+ print_tagq(h, t);
+ breakline = 0;
+ while (p < pend && (*p == ' ' || *p == ASCII_NBRSP))
+ p++;
+ continue;
+ }
if (p >= pend)
break;
+ if (*p == ' ') {
+ print_endword(h);
+ p++;
+ continue;
+ }
+
if (print_escape(h, *p++))
continue;
@@ -417,6 +433,9 @@ print_encode(struct html *h, const char *p, const char *pend, int norecurse)
if (c <= 0)
continue;
break;
+ case ESCAPE_BREAK:
+ breakline = 1;
+ continue;
case ESCAPE_NOSPACE:
if ('\0' == *p)
nospace = 1;
diff --git a/mandoc.c b/mandoc.c
index 355e6bfd..7dfeec77 100644
--- a/mandoc.c
+++ b/mandoc.c
@@ -96,6 +96,8 @@ mandoc_escape(const char **end, const char **start, int *sz)
case ',':
case '/':
return ESCAPE_IGNORE;
+ case 'p':
+ return ESCAPE_BREAK;
/*
* The \z escape is supposed to output the following
diff --git a/mandoc.h b/mandoc.h
index 3f2a7e1c..81335ff8 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -423,6 +423,7 @@ enum mandoc_esc {
ESCAPE_FONTPREV, /* previous font mode */
ESCAPE_NUMBERED, /* a numbered glyph */
ESCAPE_UNICODE, /* a unicode codepoint */
+ ESCAPE_BREAK, /* break the output line */
ESCAPE_NOSPACE, /* suppress space if the last on a line */
ESCAPE_HORIZ, /* horizontal movement */
ESCAPE_HLINE, /* horizontal line drawing */
diff --git a/mdoc_markdown.c b/mdoc_markdown.c
index cc9be29b..6b8b0841 100644
--- a/mdoc_markdown.c
+++ b/mdoc_markdown.c
@@ -493,7 +493,7 @@ md_word(const char *s)
{
const char *seq, *prevfont, *currfont, *nextfont;
char c;
- int bs, sz, uc;
+ int bs, sz, uc, breakline;
/* No spacing before closing delimiters. */
if (s[0] != '\0' && s[1] == '\0' &&
@@ -510,6 +510,7 @@ md_word(const char *s)
if ((s[0] == '(' || s[0] == '[') && s[1] == '\0')
outflags &= ~MD_spc;
+ breakline = 0;
prevfont = currfont = "";
while ((c = *s++) != '\0') {
bs = 0;
@@ -595,6 +596,9 @@ md_word(const char *s)
case ESCAPE_FONTPREV:
nextfont = prevfont;
break;
+ case ESCAPE_BREAK:
+ breakline = 1;
+ break;
case ESCAPE_NOSPACE:
case ESCAPE_SKIPCHAR:
case ESCAPE_OVERSTRIKE:
@@ -642,6 +646,13 @@ md_word(const char *s)
if (bs)
putchar('\\');
md_char(c);
+ if (breakline &&
+ (*s == '\0' || *s == ' ' || *s == ASCII_NBRSP)) {
+ printf(" \n");
+ breakline = 0;
+ while (*s == ' ' || *s == ASCII_NBRSP)
+ s++;
+ }
}
if (*currfont != '\0') {
outflags &= ~MD_spc;
diff --git a/regress/roff/esc/Makefile b/regress/roff/esc/Makefile
index f0860368..4c8e492b 100644
--- a/regress/roff/esc/Makefile
+++ b/regress/roff/esc/Makefile
@@ -1,6 +1,6 @@
# $OpenBSD: Makefile,v 1.11 2015/04/29 18:32:57 schwarze Exp $
-REGRESS_TARGETS = one two multi B c c_man e f h o w z ignore
+REGRESS_TARGETS = one two multi B c c_man e f h o p w z ignore
LINT_TARGETS = B h w ignore
.include <bsd.regress.mk>
diff --git a/regress/roff/esc/p.in b/regress/roff/esc/p.in
new file mode 100644
index 00000000..b94ab13a
--- /dev/null
+++ b/regress/roff/esc/p.in
@@ -0,0 +1,15 @@
+.Dd June 14, 2017
+.Dt ESC-P 1
+.Os OpenBSD
+.Sh NAME
+.Nm esc-p
+.Nd line break escape sequence
+.Sh DESCRIPTION
+no blank: line one\pline two
+.Pp
+blank after esc: line one\p line two
+.Pp
+blank before esc: line one \pline two
+.Pp
+at eol: line one\p
+line two
diff --git a/regress/roff/esc/p.out_ascii b/regress/roff/esc/p.out_ascii
new file mode 100644
index 00000000..488e2c61
--- /dev/null
+++ b/regress/roff/esc/p.out_ascii
@@ -0,0 +1,19 @@
+ESC-P(1) General Commands Manual ESC-P(1)
+
+NNAAMMEE
+ eesscc--pp - line break escape sequence
+
+DDEESSCCRRIIPPTTIIOONN
+ no blank: line oneline
+ two
+
+ blank after esc: line one
+ line two
+
+ blank before esc: line one line
+ two
+
+ at eol: line one
+ line two
+
+OpenBSD June 14, 2017 OpenBSD
diff --git a/roff.7 b/roff.7
index 0d8b1d25..5bf16141 100644
--- a/roff.7
+++ b/roff.7
@@ -1991,6 +1991,8 @@ Overstrike, writing all the characters contained in the
to the same output position.
In terminal and HTML output modes,
only the last one of the characters is visible.
+.Ss \ep
+Break the output line at the end of the current word.
.Ss \eR\(aq Ns Ar name Oo +|- Oc Ns Ar number Ns \(aq
Set number register; ignored by
.Xr mandoc 1 .
diff --git a/term.c b/term.c
index bbadef66..a7236f87 100644
--- a/term.c
+++ b/term.c
@@ -116,6 +116,7 @@ term_flushln(struct termp *p)
size_t jhy; /* last hyph before overflow w/r/t j */
size_t maxvis; /* output position of visible boundary */
int ntab; /* number of tabs to prepend */
+ int breakline; /* after this word */
vbl = (p->flags & TERMP_NOPAD) || p->tcol->offset < p->viscol ?
0 : p->tcol->offset - p->viscol;
@@ -155,7 +156,13 @@ term_flushln(struct termp *p)
*/
jhy = 0;
+ breakline = 0;
for (j = p->tcol->col; j < p->tcol->lastcol; j++) {
+ if (p->tcol->buf[j] == '\n') {
+ if ((p->flags & TERMP_BRIND) == 0)
+ breakline = 1;
+ continue;
+ }
if (p->tcol->buf[j] == ' ' || p->tcol->buf[j] == '\t')
break;
@@ -221,6 +228,8 @@ term_flushln(struct termp *p)
for ( ; p->tcol->col < p->tcol->lastcol; p->tcol->col++) {
if (vend > bp && jhy > 0 && p->tcol->col > jhy)
break;
+ if (p->tcol->buf[p->tcol->col] == '\n')
+ continue;
if (p->tcol->buf[p->tcol->col] == '\t')
break;
if (p->tcol->buf[p->tcol->col] == ' ') {
@@ -260,6 +269,26 @@ term_flushln(struct termp *p)
p->tcol->buf[p->tcol->col]);
}
vis = vend;
+
+ if (breakline == 0)
+ continue;
+
+ /* Explicitly requested output line break. */
+
+ if (p->flags & TERMP_MULTICOL)
+ return;
+
+ endline(p);
+ breakline = 0;
+ vis = vend = 0;
+
+ /* Re-establish indentation. */
+
+ vbl = p->tcol->offset;
+ maxvis = p->tcol->rmargin > vbl ?
+ p->tcol->rmargin - vbl : 0;
+ bp = !(p->flags & TERMP_NOBREAK) ? maxvis :
+ p->maxrmargin > vbl ? p->maxrmargin - vbl : 0;
}
/*
@@ -487,6 +516,9 @@ term_word(struct termp *p, const char *word)
case ESCAPE_FONTPREV:
term_fontlast(p);
continue;
+ case ESCAPE_BREAK:
+ bufferc(p, '\n');
+ continue;
case ESCAPE_NOSPACE:
if (p->flags & TERMP_BACKAFTER)
p->flags &= ~TERMP_BACKAFTER;