diff options
author | Kristaps Dzonsons <kristaps@bsd.lv> | 2009-11-12 05:50:12 +0000 |
---|---|---|
committer | Kristaps Dzonsons <kristaps@bsd.lv> | 2009-11-12 05:50:12 +0000 |
commit | 98a07e7455f567f7e0ec8f62788f883a8efd7eae (patch) | |
tree | df0f64f0018c106998276752306943790552bf8a | |
parent | 8d9b3e337843a72a4e23e3cc12bf7337cde4d8b9 (diff) | |
download | mandoc-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.7 | 4 | ||||
-rw-r--r-- | man_term.c | 114 | ||||
-rw-r--r-- | mdoc.7 | 27 | ||||
-rw-r--r-- | mdoc_term.c | 144 | ||||
-rw-r--r-- | term.c | 234 | ||||
-rw-r--r-- | term.h | 23 |
6 files changed, 303 insertions, 243 deletions
@@ -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 @@ -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); @@ -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); } @@ -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); } @@ -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*/ |