summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2009-11-12 05:50:12 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2009-11-12 05:50:12 +0000
commit98a07e7455f567f7e0ec8f62788f883a8efd7eae (patch)
treedf0f64f0018c106998276752306943790552bf8a
parent8d9b3e337843a72a4e23e3cc12bf7337cde4d8b9 (diff)
downloadmandoc-98a07e7455f567f7e0ec8f62788f883a8efd7eae.tar.gz
Basically re-wrote -Tascii font handling: instead of incrementers for
bold and underline, we use a stack (no cascading, no double-font-mode). Font modes with \f only affect the current stack point, as documented in mdoc.7 and man.7. While -mdoc stacks fonts with embedded macros, -man replaces them (the stack is always size 1). This works for all invocations in supported systems' manual corpora to date. It doesn't support groff's insanity with line-scoped \f as documented in mdoc.7.
-rw-r--r--man.74
-rw-r--r--man_term.c114
-rw-r--r--mdoc.727
-rw-r--r--mdoc_term.c144
-rw-r--r--term.c234
-rw-r--r--term.h23
6 files changed, 303 insertions, 243 deletions
diff --git a/man.7 b/man.7
index 1d9fc3c9..59060167 100644
--- a/man.7
+++ b/man.7
@@ -115,7 +115,9 @@ escape followed by an indicator: B (bold), I, (italic), R (Roman), or P
.D1 \efBbold\efR \efIitalic\efP
.Pp
A numerical representation 3, 2, or 1 (bold, italic, and Roman,
-respectively) may be used instead.
+respectively) may be used instead. A text decoration is only valid, if
+specified in free-form text, until the next macro invocation; if
+specified within a macro, it's only valid until the macro closes scope.
.Pp
Text may also be sized with the
.Sq \es
diff --git a/man_term.c b/man_term.c
index f1d39f24..6932c3fb 100644
--- a/man_term.c
+++ b/man_term.c
@@ -73,7 +73,7 @@ static int a2height(const struct man_node *);
static void print_man_head(struct termp *,
const struct man_meta *);
-static void print_man_body(DECL_ARGS);
+static void print_man_nodelist(DECL_ARGS);
static void print_man_node(DECL_ARGS);
static void print_man_foot(struct termp *,
const struct man_meta *);
@@ -96,11 +96,8 @@ static int pre_br(DECL_ARGS);
static int pre_fi(DECL_ARGS);
static int pre_ign(DECL_ARGS);
static int pre_nf(DECL_ARGS);
-static int pre_r(DECL_ARGS);
static int pre_sp(DECL_ARGS);
-static void post_B(DECL_ARGS);
-static void post_I(DECL_ARGS);
static void post_IP(DECL_ARGS);
static void post_HP(DECL_ARGS);
static void post_RS(DECL_ARGS);
@@ -121,14 +118,14 @@ static const struct termact termacts[MAN_MAX] = {
{ pre_IP, post_IP }, /* IP */
{ pre_HP, post_HP }, /* HP */
{ NULL, NULL }, /* SM */
- { pre_B, post_B }, /* SB */
+ { pre_B, NULL }, /* SB */
{ pre_BI, NULL }, /* BI */
{ pre_BI, NULL }, /* IB */
{ pre_RB, NULL }, /* BR */
{ pre_RB, NULL }, /* RB */
{ NULL, NULL }, /* R */
- { pre_B, post_B }, /* B */
- { pre_I, post_I }, /* I */
+ { pre_B, NULL }, /* B */
+ { pre_I, NULL }, /* I */
{ pre_RI, NULL }, /* IR */
{ pre_RI, NULL }, /* RI */
{ NULL, NULL }, /* na */
@@ -136,7 +133,7 @@ static const struct termact termacts[MAN_MAX] = {
{ pre_sp, NULL }, /* sp */
{ pre_nf, NULL }, /* nf */
{ pre_fi, NULL }, /* fi */
- { pre_r, NULL }, /* r */
+ { NULL, NULL }, /* r */
{ NULL, NULL }, /* RE */
{ pre_RS, post_RS }, /* RS */
{ pre_ign, NULL }, /* DT */
@@ -177,7 +174,7 @@ terminal_man(void *arg, const struct man *man)
mt.offset = INDENT;
if (n->child)
- print_man_body(p, &mt, n->child, m);
+ print_man_nodelist(p, &mt, n->child, m);
print_man_foot(p, m);
}
@@ -241,17 +238,7 @@ static int
pre_I(DECL_ARGS)
{
- p->under++;
- return(1);
-}
-
-
-/* ARGSUSED */
-static int
-pre_r(DECL_ARGS)
-{
-
- p->bold = p->under = 0;
+ term_fontrepl(p, TERMFONT_UNDER);
return(1);
}
@@ -261,17 +248,9 @@ static void
post_i(DECL_ARGS)
{
- if (n->nchild)
- p->under--;
-}
-
-
-/* ARGSUSED */
-static void
-post_I(DECL_ARGS)
-{
-
- p->under--;
+ /* FIXME */
+ /*if (n->nchild)
+ p->under--;*/
}
@@ -305,19 +284,16 @@ pre_RB(DECL_ARGS)
for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
if (i % 2 && MAN_RB == n->tok)
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
else if ( ! (i % 2) && MAN_RB != n->tok)
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
+ else
+ term_fontrepl(p, TERMFONT_NONE);
if (i > 0)
p->flags |= TERMP_NOSPACE;
print_man_node(p, mt, nn, m);
-
- if (i % 2 && MAN_RB == n->tok)
- p->bold--;
- else if ( ! (i % 2) && MAN_RB != n->tok)
- p->bold--;
}
return(0);
}
@@ -332,18 +308,16 @@ pre_RI(DECL_ARGS)
for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
if (i % 2 && MAN_RI == n->tok)
- p->under++;
+ term_fontrepl(p, TERMFONT_UNDER);
else if ( ! (i % 2) && MAN_RI != n->tok)
- p->under++;
+ term_fontrepl(p, TERMFONT_UNDER);
+ else
+ term_fontrepl(p, TERMFONT_NONE);
if (i > 0)
p->flags |= TERMP_NOSPACE;
- print_man_node(p, mt, nn, m);
- if (i % 2 && MAN_RI == n->tok)
- p->under--;
- else if ( ! (i % 2) && MAN_RI != n->tok)
- p->under--;
+ print_man_node(p, mt, nn, m);
}
return(0);
}
@@ -358,26 +332,18 @@ pre_BI(DECL_ARGS)
for (i = 0, nn = n->child; nn; nn = nn->next, i++) {
if (i % 2 && MAN_BI == n->tok)
- p->under++;
+ term_fontrepl(p, TERMFONT_UNDER);
else if (i % 2)
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
else if (MAN_BI == n->tok)
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
else
- p->under++;
+ term_fontrepl(p, TERMFONT_UNDER);
if (i)
p->flags |= TERMP_NOSPACE;
- print_man_node(p, mt, nn, m);
- if (i % 2 && MAN_BI == n->tok)
- p->under--;
- else if (i % 2)
- p->bold--;
- else if (MAN_BI == n->tok)
- p->bold--;
- else
- p->under--;
+ print_man_node(p, mt, nn, m);
}
return(0);
}
@@ -388,21 +354,12 @@ static int
pre_B(DECL_ARGS)
{
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
return(1);
}
/* ARGSUSED */
-static void
-post_B(DECL_ARGS)
-{
-
- p->bold--;
-}
-
-
-/* ARGSUSED */
static int
pre_sp(DECL_ARGS)
{
@@ -705,7 +662,7 @@ pre_SS(DECL_ARGS)
term_vspace(p);
break;
case (MAN_HEAD):
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
p->offset = HALFINDENT;
break;
case (MAN_BODY):
@@ -727,7 +684,6 @@ post_SS(DECL_ARGS)
switch (n->type) {
case (MAN_HEAD):
term_newln(p);
- p->bold--;
break;
case (MAN_BODY):
term_newln(p);
@@ -754,7 +710,7 @@ pre_SH(DECL_ARGS)
term_vspace(p);
break;
case (MAN_HEAD):
- p->bold++;
+ term_fontrepl(p, TERMFONT_BOLD);
p->offset = 0;
break;
case (MAN_BODY):
@@ -776,7 +732,6 @@ post_SH(DECL_ARGS)
switch (n->type) {
case (MAN_HEAD):
term_newln(p);
- p->bold--;
break;
case (MAN_BODY):
term_newln(p);
@@ -861,39 +816,40 @@ print_man_node(DECL_ARGS)
if (sz >= 2 && n->string[sz - 1] == 'c' &&
n->string[sz - 2] == '\\')
p->flags |= TERMP_NOSPACE;
+
/* FIXME: this means that macro lines are munged! */
+
if (MANT_LITERAL & mt->fl) {
p->flags |= TERMP_NOSPACE;
term_flushln(p);
}
break;
default:
+ term_fontrepl(p, TERMFONT_NONE);
if (termacts[n->tok].pre)
c = (*termacts[n->tok].pre)(p, mt, n, m);
break;
}
if (c && n->child)
- print_man_body(p, mt, n->child, m);
+ print_man_nodelist(p, mt, n->child, m);
if (MAN_TEXT != n->type) {
if (termacts[n->tok].post)
(*termacts[n->tok].post)(p, mt, n, m);
-
- /* Reset metafont upon exit from macro. */
- p->metafont = 0;
+ term_fontrepl(p, TERMFONT_NONE);
}
}
static void
-print_man_body(DECL_ARGS)
+print_man_nodelist(DECL_ARGS)
{
print_man_node(p, mt, n, m);
if ( ! n->next)
return;
- print_man_body(p, mt, n->next, m);
+ print_man_nodelist(p, mt, n->next, m);
}
@@ -902,7 +858,7 @@ print_man_foot(struct termp *p, const struct man_meta *meta)
{
char buf[DATESIZ];
- p->metafont = 0;
+ term_fontrepl(p, TERMFONT_NONE);
time2a(meta->date, buf, DATESIZ);
diff --git a/mdoc.7 b/mdoc.7
index 8f4e20a3..8ef0435f 100644
--- a/mdoc.7
+++ b/mdoc.7
@@ -137,7 +137,17 @@ escape followed by an indicator: B (bold), I, (italic), R (Roman), or P
.D1 \efBbold\efR \efIitalic\efP
.Pp
A numerical representation 3, 2, or 1 (bold, italic, and Roman,
-respectively) may be used instead.
+respectively) may be used instead. A text decoration is valid within
+the current font scope only: if a macro opens a font scope alongside
+its own scope, such as
+.Sx \&Bf
+.Cm \&Sy ,
+in-scope invocations of
+.Sq \ef
+are only valid within the font scope of the macro. If
+.Sq \ef
+is specified outside of any font scope, such as in unenclosed, free-form
+text, it will affect the remainder of the document.
.Pp
Text may also be sized with the
.Sq \es
@@ -1820,9 +1830,16 @@ file re-write
.Pp
.Bl -dash -compact
.It
+.Xr groff 1
+behaves strangely (even between versions) when specifying
+.Sq \ef
+escapes within line-macro scopes. These aberrations have been
+normalised.
+.It
Negative scaling units are now truncated to zero instead of creating
interesting conditions, such as with
-.Sq \&sp -1i .
+.Sx \&sp
+.Cm \-1i .
Furthermore, the
.Sq f
scaling unit, while accepted, is rendered as the default unit.
@@ -1832,7 +1849,8 @@ standalone double-quote in formatted output. This idiosyncratic
behaviour is no longer applicable.
.It
Display types
-.Sx \&Bd Fl center
+.Sx \&Bd
+.Fl center
and
.Fl right
are aliases for
@@ -1862,7 +1880,8 @@ made historic groff
.Qq go orbital
but is a proper delimiter in this implementation.
.It
-.Sx \&It Fl nested
+.Sx \&It
+.Fl nested
is assumed for all lists (it wasn't in historic groff): any list may be
nested and
.Fl enum
diff --git a/mdoc_term.c b/mdoc_term.c
index ba89561b..de73b311 100644
--- a/mdoc_term.c
+++ b/mdoc_term.c
@@ -59,9 +59,9 @@ static int arg_listtype(const struct mdoc_node *);
static void print_bvspace(struct termp *,
const struct mdoc_node *,
const struct mdoc_node *);
-static void print_node(DECL_ARGS);
-static void print_head(DECL_ARGS);
-static void print_body(DECL_ARGS);
+static void print_mdoc_node(DECL_ARGS);
+static void print_mdoc_head(DECL_ARGS);
+static void print_mdoc_nodelist(DECL_ARGS);
static void print_foot(DECL_ARGS);
#ifdef __linux__
@@ -116,6 +116,7 @@ static int termp_fo_pre(DECL_ARGS);
static int termp_ft_pre(DECL_ARGS);
static int termp_in_pre(DECL_ARGS);
static int termp_it_pre(DECL_ARGS);
+static int termp_li_pre(DECL_ARGS);
static int termp_lk_pre(DECL_ARGS);
static int termp_nd_pre(DECL_ARGS);
static int termp_nm_pre(DECL_ARGS);
@@ -167,7 +168,7 @@ static const struct termact termacts[MDOC_MAX] = {
{ termp_ft_pre, termp_ft_post }, /* Ft */
{ termp_bold_pre, NULL }, /* Ic */
{ termp_in_pre, termp_in_post }, /* In */
- { NULL, NULL }, /* Li */
+ { termp_li_pre, NULL }, /* Li */
{ termp_nd_pre, NULL }, /* Nd */
{ termp_nm_pre, NULL }, /* Nm */
{ termp_op_pre, termp_op_post }, /* Op */
@@ -283,36 +284,36 @@ terminal_mdoc(void *arg, const struct mdoc *mdoc)
n = mdoc_node(mdoc);
m = mdoc_meta(mdoc);
- print_head(p, NULL, m, n);
+ print_mdoc_head(p, NULL, m, n);
if (n->child)
- print_body(p, NULL, m, n->child);
+ print_mdoc_nodelist(p, NULL, m, n->child);
print_foot(p, NULL, m, n);
}
static void
-print_body(DECL_ARGS)
+print_mdoc_nodelist(DECL_ARGS)
{
- print_node(p, pair, m, n);
+ print_mdoc_node(p, pair, m, n);
if (n->next)
- print_body(p, pair, m, n->next);
+ print_mdoc_nodelist(p, pair, m, n->next);
}
/* ARGSUSED */
static void
-print_node(DECL_ARGS)
+print_mdoc_node(DECL_ARGS)
{
- int chld, bold, under;
+ int chld;
+ const void *font;
struct termpair npair;
size_t offset, rmargin;
chld = 1;
offset = p->offset;
rmargin = p->rmargin;
- bold = p->bold;
- under = p->under;
+ font = term_fontq(p);
memset(&npair, 0, sizeof(struct termpair));
npair.ppair = pair;
@@ -322,17 +323,11 @@ print_node(DECL_ARGS)
chld = (*termacts[n->tok].pre)(p, &npair, m, n);
} else
term_word(p, n->string);
- if (chld && n->child)
- print_body(p, &npair, m, n->child);
- /*
- * XXX - if bold/under were to span scopes, this wouldn't be
- * possible, but because decoration is always in-scope, we can
- * get away with this.
- */
+ if (chld && n->child)
+ print_mdoc_nodelist(p, &npair, m, n->child);
- p->bold = bold;
- p->under = under;
+ term_fontpopq(p, font);
if (MDOC_TEXT != n->type)
if (termacts[n->tok].post)
@@ -349,8 +344,7 @@ print_foot(DECL_ARGS)
{
char buf[DATESIZ], os[BUFSIZ];
- /* Disable meta-fonts. */
- p->metafont = 0;
+ term_fontrepl(p, TERMFONT_NONE);
/*
* Output the footer in new-groff style, that is, three columns
@@ -393,10 +387,9 @@ print_foot(DECL_ARGS)
}
-/* FIXME: put in utility library. */
/* ARGSUSED */
static void
-print_head(DECL_ARGS)
+print_mdoc_head(DECL_ARGS)
{
char buf[BUFSIZ], title[BUFSIZ];
@@ -782,7 +775,7 @@ termp_it_pre(DECL_ARGS)
switch (type) {
case (MDOC_Diag):
if (MDOC_HEAD == n->type)
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
break;
default:
break;
@@ -920,16 +913,16 @@ termp_it_pre(DECL_ARGS)
if (MDOC_HEAD == n->type)
switch (type) {
case (MDOC_Bullet):
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, "\\[bu]");
- p->bold--;
+ term_fontpop(p);
break;
case (MDOC_Dash):
/* FALLTHROUGH */
case (MDOC_Hyphen):
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, "\\(hy");
- p->bold--;
+ term_fontpop(p);
break;
case (MDOC_Enum):
(pair->ppair->ppair->count)++;
@@ -1011,7 +1004,9 @@ termp_nm_pre(DECL_ARGS)
if (SEC_SYNOPSIS == n->sec)
term_newln(p);
- p->bold++;
+
+ term_fontpush(p, TERMFONT_BOLD);
+
if (NULL == n->child)
term_word(p, m->name);
return(1);
@@ -1023,7 +1018,7 @@ static int
termp_fl_pre(DECL_ARGS)
{
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, "\\-");
p->flags |= TERMP_NOSPACE;
return(1);
@@ -1121,9 +1116,9 @@ termp_rv_pre(DECL_ARGS)
term_word(p, "The");
for (nn = n->child; nn; nn = nn->next) {
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, nn->string);
- p->bold--;
+ term_fontpop(p);
p->flags |= TERMP_NOSPACE;
if (nn->next && NULL == nn->next->next)
term_word(p, "(), and");
@@ -1141,9 +1136,9 @@ termp_rv_pre(DECL_ARGS)
term_word(p, "the value 0 if successful; otherwise the value "
"-1 is returned and the global variable");
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
term_word(p, "errno");
- p->under--;
+ term_fontpop(p);
term_word(p, "is set to indicate the error.");
@@ -1160,9 +1155,9 @@ termp_ex_pre(DECL_ARGS)
term_word(p, "The");
for (nn = n->child; nn; nn = nn->next) {
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, nn->string);
- p->bold--;
+ term_fontpop(p);
p->flags |= TERMP_NOSPACE;
if (nn->next && NULL == nn->next->next)
term_word(p, ", and");
@@ -1264,7 +1259,7 @@ static int
termp_bold_pre(DECL_ARGS)
{
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
return(1);
}
@@ -1298,7 +1293,7 @@ termp_sh_pre(DECL_ARGS)
term_vspace(p);
break;
case (MDOC_HEAD):
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
break;
case (MDOC_BODY):
p->offset = INDENT;
@@ -1433,7 +1428,8 @@ termp_ft_pre(DECL_ARGS)
if (SEC_SYNOPSIS == n->sec)
if (n->prev && MDOC_Fo == n->prev->tok)
term_vspace(p);
- p->under++;
+
+ term_fontpush(p, TERMFONT_UNDER);
return(1);
}
@@ -1454,17 +1450,18 @@ termp_fn_pre(DECL_ARGS)
{
const struct mdoc_node *nn;
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_word(p, n->child->string);
- p->bold--;
+ term_fontpop(p);
p->flags |= TERMP_NOSPACE;
term_word(p, "(");
for (nn = n->child->next; nn; nn = nn->next) {
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
term_word(p, nn->string);
- p->under--;
+ term_fontpop(p);
+
if (nn->next)
term_word(p, ",");
}
@@ -1495,14 +1492,15 @@ termp_fa_pre(DECL_ARGS)
const struct mdoc_node *nn;
if (n->parent->tok != MDOC_Fo) {
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
return(1);
}
for (nn = n->child; nn; nn = nn->next) {
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
term_word(p, nn->string);
- p->under--;
+ term_fontpop(p);
+
if (nn->next)
term_word(p, ",");
}
@@ -1564,7 +1562,7 @@ termp_bd_pre(DECL_ARGS)
for (nn = n->child; nn; nn = nn->next) {
p->flags |= TERMP_NOSPACE;
- print_node(p, pair, m, nn);
+ print_mdoc_node(p, pair, m, nn);
if (NULL == nn->next)
continue;
if (nn->prev && nn->prev->line < nn->line)
@@ -1718,7 +1716,7 @@ termp_ss_pre(DECL_ARGS)
term_vspace(p);
break;
case (MDOC_HEAD):
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
p->offset = HALFINDENT;
break;
default:
@@ -1744,7 +1742,7 @@ static int
termp_cd_pre(DECL_ARGS)
{
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
term_newln(p);
return(1);
}
@@ -1755,7 +1753,7 @@ static int
termp_in_pre(DECL_ARGS)
{
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
if (SEC_SYNOPSIS == n->sec)
term_word(p, "#include");
@@ -1770,10 +1768,10 @@ static void
termp_in_post(DECL_ARGS)
{
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
p->flags |= TERMP_NOSPACE;
term_word(p, ">");
- p->bold--;
+ term_fontpop(p);
if (SEC_SYNOPSIS != n->sec)
return;
@@ -1905,12 +1903,12 @@ termp_fo_pre(DECL_ARGS)
} else if (MDOC_HEAD != n->type)
return(1);
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
for (nn = n->child; nn; nn = nn->next) {
assert(MDOC_TEXT == nn->type);
term_word(p, nn->string);
}
- p->bold--;
+ term_fontpop(p);
return(0);
}
@@ -1944,18 +1942,22 @@ termp_bf_pre(DECL_ARGS)
if (NULL == (nn = n->head->child)) {
if (arg_hasattr(MDOC_Emphasis, n))
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
else if (arg_hasattr(MDOC_Symbolic, n))
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
+ else
+ term_fontpush(p, TERMFONT_NONE);
return(1);
}
assert(MDOC_TEXT == nn->type);
if (0 == strcmp("Em", nn->string))
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
else if (0 == strcmp("Sy", nn->string))
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
+ else
+ term_fontpush(p, TERMFONT_NONE);
return(1);
}
@@ -2011,26 +2013,36 @@ termp____post(DECL_ARGS)
/* ARGSUSED */
static int
+termp_li_pre(DECL_ARGS)
+{
+
+ term_fontpush(p, TERMFONT_NONE);
+ return(1);
+}
+
+
+/* ARGSUSED */
+static int
termp_lk_pre(DECL_ARGS)
{
const struct mdoc_node *nn;
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
nn = n->child;
if (NULL == nn->next)
return(1);
term_word(p, nn->string);
- p->under--;
+ term_fontpop(p);
p->flags |= TERMP_NOSPACE;
term_word(p, ":");
- p->bold++;
+ term_fontpush(p, TERMFONT_BOLD);
for (nn = nn->next; nn; nn = nn->next)
term_word(p, nn->string);
- p->bold--;
+ term_fontpop(p);
return(0);
}
@@ -2041,7 +2053,7 @@ static int
termp_under_pre(DECL_ARGS)
{
- p->under++;
+ term_fontpush(p, TERMFONT_UNDER);
return(1);
}
diff --git a/term.c b/term.c
index b0c51bd6..86d53ed7 100644
--- a/term.c
+++ b/term.c
@@ -28,18 +28,14 @@
#include "mdoc.h"
#include "main.h"
-/* FIXME: accomodate non-breaking, non-collapsing white-space. */
-/* FIXME: accomodate non-breaking, collapsing white-space. */
-
static struct termp *term_alloc(enum termenc);
static void term_free(struct termp *);
-
-static void do_special(struct termp *,
- const char *, size_t);
-static void do_reserved(struct termp *,
- const char *, size_t);
-static void buffer(struct termp *, char);
-static void encode(struct termp *, char);
+static void spec(struct termp *, const char *, size_t);
+static void res(struct termp *, const char *, size_t);
+static void buffera(struct termp *, const char *, size_t);
+static void bufferc(struct termp *, char);
+static void adjbuf(struct termp *p, size_t);
+static void encode(struct termp *, const char *, size_t);
void *
@@ -320,48 +316,91 @@ term_vspace(struct termp *p)
static void
-do_special(struct termp *p, const char *word, size_t len)
+spec(struct termp *p, const char *word, size_t len)
{
const char *rhs;
size_t sz;
- int i;
rhs = chars_a2ascii(p->symtab, word, len, &sz);
-
- if (NULL == rhs) {
-#if 0
- fputs("Unknown special character: ", stderr);
- for (i = 0; i < (int)len; i++)
- fputc(word[i], stderr);
- fputc('\n', stderr);
-#endif
- return;
- }
- for (i = 0; i < (int)sz; i++)
- encode(p, rhs[i]);
+ if (rhs)
+ encode(p, rhs, sz);
}
static void
-do_reserved(struct termp *p, const char *word, size_t len)
+res(struct termp *p, const char *word, size_t len)
{
const char *rhs;
size_t sz;
- int i;
rhs = chars_a2res(p->symtab, word, len, &sz);
+ if (rhs)
+ encode(p, rhs, sz);
+}
- if (NULL == rhs) {
-#if 0
- fputs("Unknown reserved word: ", stderr);
- for (i = 0; i < (int)len; i++)
- fputc(word[i], stderr);
- fputc('\n', stderr);
-#endif
- return;
- }
- for (i = 0; i < (int)sz; i++)
- encode(p, rhs[i]);
+
+void
+term_fontlast(struct termp *p)
+{
+ enum termfont f;
+
+ f = p->fontl;
+ p->fontl = p->fontq[p->fonti];
+ p->fontq[p->fonti] = f;
+}
+
+
+void
+term_fontrepl(struct termp *p, enum termfont f)
+{
+
+ p->fontl = p->fontq[p->fonti];
+ p->fontq[p->fonti] = f;
+}
+
+
+void
+term_fontpush(struct termp *p, enum termfont f)
+{
+
+ assert(p->fonti + 1 < 10);
+ p->fontl = p->fontq[p->fonti];
+ p->fontq[++p->fonti] = f;
+}
+
+
+const void *
+term_fontq(struct termp *p)
+{
+
+ return(&p->fontq[p->fonti]);
+}
+
+
+enum termfont
+term_fonttop(struct termp *p)
+{
+
+ return(p->fontq[p->fonti]);
+}
+
+
+void
+term_fontpopq(struct termp *p, const void *key)
+{
+
+ while (p->fonti >= 0 && key != &p->fontq[p->fonti])
+ p->fonti--;
+ assert(p->fonti >= 0);
+}
+
+
+void
+term_fontpop(struct termp *p)
+{
+
+ assert(p->fonti);
+ p->fonti--;
}
@@ -374,7 +413,7 @@ void
term_word(struct termp *p, const char *word)
{
const char *sv, *seq;
- int sz, meta;
+ int sz;
size_t ssz;
enum roffdeco deco;
@@ -407,20 +446,16 @@ term_word(struct termp *p, const char *word)
}
if ( ! (TERMP_NOSPACE & p->flags))
- buffer(p, ' ');
+ bufferc(p, ' ');
if ( ! (p->flags & TERMP_NONOSPACE))
p->flags &= ~TERMP_NOSPACE;
- /*
- * FIXME: it's faster to put the metafont conditional here,
- * because most of the time we're not a metafont and can use
- * strcspn and fwrite.
- */
+ /* FIXME: use strcspn. */
while (*word) {
if ('\\' != *word) {
- encode(p, *word);
+ encode(p, word, 1);
word++;
continue;
}
@@ -430,28 +465,22 @@ term_word(struct termp *p, const char *word)
switch (deco) {
case (DECO_RESERVED):
- do_reserved(p, seq, ssz);
+ res(p, seq, ssz);
break;
case (DECO_SPECIAL):
- do_special(p, seq, ssz);
+ spec(p, seq, ssz);
break;
case (DECO_BOLD):
- p->metamask = p->metafont;
- p->metafont |= METAF_BOLD;
+ term_fontrepl(p, TERMFONT_BOLD);
break;
case (DECO_ITALIC):
- p->metamask = p->metafont;
- p->metafont |= METAF_UNDER;
+ term_fontrepl(p, TERMFONT_UNDER);
break;
case (DECO_ROMAN):
- p->metamask = p->metafont;
- p->metafont &= ~METAF_UNDER;
- p->metafont &= ~METAF_BOLD;
+ term_fontrepl(p, TERMFONT_NONE);
break;
case (DECO_PREVIOUS):
- meta = p->metamask;
- p->metamask = p->metafont;
- p->metafont = meta;
+ term_fontlast(p);
break;
default:
break;
@@ -474,46 +503,77 @@ term_word(struct termp *p, const char *word)
}
-/*
- * Insert a single character into the line-buffer. If the buffer's
- * space is exceeded, then allocate more space by doubling the buffer
- * size.
- */
static void
-buffer(struct termp *p, char c)
+adjbuf(struct termp *p, size_t sz)
{
- size_t s;
-
- if (p->col + 1 >= p->maxcols) {
- if (0 == p->maxcols)
- p->maxcols = 256;
- s = p->maxcols * 2;
- p->buf = realloc(p->buf, s);
- if (NULL == p->buf) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
- p->maxcols = s;
+
+ if (0 == p->maxcols)
+ p->maxcols = 1024;
+ while (sz >= p->maxcols)
+ p->maxcols <<= 2;
+
+ p->buf = realloc(p->buf, p->maxcols);
+ if (NULL == p->buf) {
+ perror(NULL);
+ exit(EXIT_FAILURE);
}
- p->buf[(int)(p->col)++] = c;
}
static void
-encode(struct termp *p, char c)
+buffera(struct termp *p, const char *word, size_t sz)
{
-
- if (isgraph((u_char)c)) {
- if (p->under || METAF_UNDER & p->metafont) {
- buffer(p, '_');
- buffer(p, 8);
- }
- if (p->bold || METAF_BOLD & p->metafont) {
- buffer(p, c);
- buffer(p, 8);
+
+ if (p->col + sz >= p->maxcols)
+ adjbuf(p, p->col + sz);
+
+ memcpy(&p->buf[p->col], word, sz);
+ p->col += sz;
+}
+
+
+static void
+bufferc(struct termp *p, char c)
+{
+
+ if (p->col + 1 >= p->maxcols)
+ adjbuf(p, p->col + 1);
+
+ p->buf[p->col++] = c;
+}
+
+
+static void
+encode(struct termp *p, const char *word, size_t sz)
+{
+ enum termfont f;
+ int i;
+
+ /*
+ * Encode and buffer a string of characters. If the current
+ * font mode is unset, buffer directly, else encode then buffer
+ * character by character.
+ */
+
+ if (TERMFONT_NONE == (f = term_fonttop(p))) {
+ buffera(p, word, sz);
+ return;
+ }
+
+ for (i = 0; i < (int)sz; i++) {
+ if ( ! isgraph((u_char)word[i])) {
+ bufferc(p, word[i]);
+ continue;
}
+
+ if (TERMFONT_UNDER == f)
+ bufferc(p, '_');
+ else
+ bufferc(p, word[i]);
+
+ bufferc(p, 8);
+ bufferc(p, word[i]);
}
- buffer(p, c);
}
diff --git a/term.h b/term.h
index ee8fd90e..2cee1723 100644
--- a/term.h
+++ b/term.h
@@ -23,6 +23,12 @@ enum termenc {
TERMENC_ASCII
};
+enum termfont {
+ TERMFONT_NONE = 0,
+ TERMFONT_BOLD,
+ TERMFONT_UNDER
+};
+
struct termp {
size_t rmargin; /* Current right margin. */
size_t maxrmargin; /* Max right margin. */
@@ -41,15 +47,12 @@ struct termp {
#define TERMP_NOSPLIT (1 << 11) /* See termp_an_pre/post(). */
#define TERMP_SPLIT (1 << 12) /* See termp_an_pre/post(). */
#define TERMP_ANPREC (1 << 13) /* See termp_an_pre(). */
- int bold;
- int under;
- int metafont; /* See do_escaped(). */
-#define METAF_BOLD (1 << 0)
-#define METAF_UNDER (1 << 1)
- int metamask; /* See do_escaped(). */
char *buf; /* Output buffer. */
enum termenc enc; /* Type of encoding. */
void *symtab; /* Encoded-symbol table. */
+ enum termfont fontl; /* Last font set. */
+ enum termfont fontq[10]; /* Symmetric fonts. */
+ int fonti; /* Index of font stack. */
};
void term_newln(struct termp *);
@@ -60,6 +63,14 @@ void term_flushln(struct termp *);
size_t term_hspan(const struct roffsu *);
size_t term_vspan(const struct roffsu *);
+enum termfont term_fonttop(struct termp *);
+const void *term_fontq(struct termp *);
+void term_fontpush(struct termp *, enum termfont);
+void term_fontpop(struct termp *);
+void term_fontpopq(struct termp *, const void *);
+void term_fontrepl(struct termp *, enum termfont);
+void term_fontlast(struct termp *);
+
__END_DECLS
#endif /*!TERM_H*/