=================================================================== RCS file: /cvs/mandoc/mdoc_man.c,v retrieving revision 1.35 retrieving revision 1.39 diff -u -p -r1.35 -r1.39 --- mandoc/mdoc_man.c 2012/07/12 08:55:48 1.35 +++ mandoc/mdoc_man.c 2012/07/14 09:07:18 1.39 @@ -1,4 +1,4 @@ -/* $Id: mdoc_man.c,v 1.35 2012/07/12 08:55:48 schwarze Exp $ */ +/* $Id: mdoc_man.c,v 1.39 2012/07/14 09:07:18 schwarze Exp $ */ /* * Copyright (c) 2011, 2012 Ingo Schwarze * @@ -102,6 +102,8 @@ static int pre_vt(DECL_ARGS); static int pre_ux(DECL_ARGS); static int pre_xr(DECL_ARGS); static void print_word(const char *); +static void print_line(const char *, int); +static void print_block(const char *, int); static void print_offs(const char *); static void print_width(const char *, const struct mdoc_node *, size_t); @@ -241,16 +243,19 @@ static const struct manact manacts[MDOC_MAX + 1] = { }; static int outflags; -#define MMAN_spc (1 << 0) -#define MMAN_spc_force (1 << 1) -#define MMAN_nl (1 << 2) -#define MMAN_br (1 << 3) -#define MMAN_sp (1 << 4) -#define MMAN_Sm (1 << 5) -#define MMAN_Bk (1 << 6) -#define MMAN_An_split (1 << 7) -#define MMAN_An_nosplit (1 << 8) +#define MMAN_spc (1 << 0) /* blank character before next word */ +#define MMAN_spc_force (1 << 1) /* even before trailing punctuation */ +#define MMAN_nl (1 << 2) /* break man(7) code line */ +#define MMAN_br (1 << 3) /* break output line */ +#define MMAN_sp (1 << 4) /* insert a blank output line */ +#define MMAN_PP (1 << 5) /* reset indentation etc. */ +#define MMAN_Sm (1 << 6) /* horizontal spacing mode */ +#define MMAN_Bk (1 << 7) /* word keep mode */ +#define MMAN_An_split (1 << 8) /* author mode is "split" */ +#define MMAN_An_nosplit (1 << 9) /* author mode is "nosplit" */ +static int TPremain; /* characters before tag is full */ + static struct { char *head; char *tail; @@ -267,7 +272,8 @@ font_push(char newfont) fontqueue.size); } *fontqueue.tail = newfont; - print_word("\\f"); + print_word(""); + printf("\\f"); putchar(newfont); outflags &= ~MMAN_spc; } @@ -279,7 +285,8 @@ font_pop(void) if (fontqueue.tail > fontqueue.head) fontqueue.tail--; outflags &= ~MMAN_spc; - print_word("\\f"); + print_word(""); + printf("\\f"); putchar(*fontqueue.tail); } @@ -287,39 +294,49 @@ static void print_word(const char *s) { - if ((MMAN_sp | MMAN_br | MMAN_nl) & outflags) { + if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) { /* * If we need a newline, print it now and start afresh. */ - if (MMAN_sp & outflags) + if (MMAN_PP & outflags) { + if ( ! (MMAN_sp & outflags)) + printf("\n.sp -1v"); + printf("\n.PP\n"); + } else if (MMAN_sp & outflags) printf("\n.sp\n"); else if (MMAN_br & outflags) printf("\n.br\n"); else if (MMAN_nl & outflags) putchar('\n'); - outflags &= ~(MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc); - } else if (MMAN_spc & outflags && '\0' != s[0]) + outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc); + if (1 == TPremain) + printf(".br\n"); + TPremain = 0; + } else if (MMAN_spc & outflags) { /* * If we need a space, only print it if * (1) it is forced by `No' or * (2) what follows is not terminating punctuation or * (3) what follows is longer than one character. */ - if (MMAN_spc_force & outflags || + if (MMAN_spc_force & outflags || '\0' == s[0] || NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) { if (MMAN_Bk & outflags) { putchar('\\'); putchar('~'); } else putchar(' '); + if (TPremain) + TPremain--; } + } /* * Reassign needing space if we're not following opening * punctuation. */ - if (MMAN_Sm & outflags && - (('(' != s[0] && '[' != s[0]) || '\0' != s[1])) + if (MMAN_Sm & outflags && ('\0' == s[0] || + (('(' != s[0] && '[' != s[0]) || '\0' != s[1]))) outflags |= MMAN_spc; else outflags &= ~MMAN_spc; @@ -337,10 +354,36 @@ print_word(const char *s) putchar((unsigned char)*s); break; } + if (TPremain) + TPremain--; } } static void +print_line(const char *s, int newflags) +{ + + outflags &= ~MMAN_br; + outflags |= MMAN_nl; + print_word(s); + outflags |= newflags; +} + +static void +print_block(const char *s, int newflags) +{ + + outflags &= ~MMAN_PP; + if (MMAN_sp & outflags) + outflags &= ~(MMAN_sp | MMAN_br); + else + print_line(".sp -1v", 0); + outflags |= MMAN_nl; + print_word(s); + outflags |= newflags; +} + +static void print_offs(const char *v) { char buf[24]; @@ -369,33 +412,38 @@ print_width(const char *v, const struct mdoc_node *chi char buf[24]; struct roffsu su; size_t sz, chsz; + int numeric, remain; - /* XXX Rough estimation, might have multiple parts. */ - chsz = (NULL != child && MDOC_TEXT == child->type) ? - strlen(child->string) : 0; - + numeric = 1; + remain = 0; if (NULL == v) sz = defsz; else if (a2roffsu(v, &su, SCALE_MAX)) { if (SCALE_EN == su.unit) sz = su.scale; else { - if (chsz) - print_word(".HP"); - else - print_word(".TP"); - print_word(v); - return; + sz = 0; + numeric = 0; } } else sz = strlen(v); - if (chsz > sz) - print_word(".HP"); - else - print_word(".TP"); - snprintf(buf, sizeof(buf), "%ldn", sz + 2); - print_word(buf); + /* XXX Rough estimation, might have multiple parts. */ + chsz = (NULL != child && MDOC_TEXT == child->type) ? + strlen(child->string) : 0; + + if (defsz && chsz > sz) + print_block(".HP", 0); + else { + print_block(".TP", 0); + remain = sz + 2; + } + if (numeric) { + snprintf(buf, sizeof(buf), "%ldn", sz + 2); + print_word(buf); + } else + print_word(v); + TPremain = remain; } void @@ -468,7 +516,8 @@ print_node(DECL_ARGS) */ if (MMAN_nl & outflags && ('.' == *n->string || '\'' == *n->string)) { - print_word("\\&"); + print_word(""); + printf("\\&"); outflags &= ~MMAN_spc; } print_word(n->string); @@ -568,7 +617,8 @@ pre__t(DECL_ARGS) if (n->parent && MDOC_Rs == n->parent->tok && n->parent->norm->Rs.quote_T) { - print_word("\""); + print_word(""); + putchar('\"'); outflags &= ~MMAN_spc; } else font_push('I'); @@ -582,7 +632,8 @@ post__t(DECL_ARGS) if (n->parent && MDOC_Rs == n->parent->tok && n->parent->norm->Rs.quote_T) { outflags &= ~MMAN_spc; - print_word("\""); + print_word(""); + putchar('\"'); } else font_pop(); post_percent(m, n); @@ -597,9 +648,10 @@ pre_sect(DECL_ARGS) if (MDOC_HEAD != n->type) return(1); - outflags |= MMAN_nl; - print_word(manacts[n->tok].prefix); - print_word("\""); + outflags |= MMAN_sp; + print_block(manacts[n->tok].prefix, 0); + print_word(""); + putchar('\"'); outflags &= ~MMAN_spc; return(1); } @@ -614,7 +666,8 @@ post_sect(DECL_ARGS) if (MDOC_HEAD != n->type) return; outflags &= ~MMAN_spc; - print_word("\""); + print_word(""); + putchar('\"'); outflags |= MMAN_nl; if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec) outflags &= ~(MMAN_An_split | MMAN_An_nosplit); @@ -697,15 +750,14 @@ static int pre_bd(DECL_ARGS) { - if (0 == n->norm->Bd.comp) - outflags |= MMAN_sp; + outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br); + if (DISP_unfilled == n->norm->Bd.type || - DISP_literal == n->norm->Bd.type) { - outflags |= MMAN_nl; - print_word(".nf"); - } - outflags |= MMAN_nl; - print_word(".RS"); + DISP_literal == n->norm->Bd.type) + print_line(".nf", 0); + if (0 == n->norm->Bd.comp && NULL != n->parent->prev) + outflags |= MMAN_sp; + print_line(".RS", 0); print_offs(n->norm->Bd.offs); outflags |= MMAN_nl; return(1); @@ -715,14 +767,10 @@ static void post_bd(DECL_ARGS) { - outflags |= MMAN_nl; - print_word(".RE"); + print_line(".RE", MMAN_nl); if (DISP_unfilled == n->norm->Bd.type || - DISP_literal == n->norm->Bd.type) { - outflags |= MMAN_nl; - print_word(".fi"); - } - outflags |= MMAN_nl; + DISP_literal == n->norm->Bd.type) + print_line(".fi", MMAN_nl); } static int @@ -797,12 +845,11 @@ pre_bl(DECL_ARGS) return(1); } - outflags |= MMAN_nl; - print_word(".TS"); - outflags |= MMAN_nl; + print_line(".TS", MMAN_nl); for (icol = 0; icol < n->norm->Bl.ncols; icol++) print_word("l"); print_word("."); + outflags |= MMAN_nl; return(1); } @@ -811,17 +858,17 @@ post_bl(DECL_ARGS) { switch (n->norm->Bl.type) { + case (LIST_column): + print_line(".TE", 0); + break; case (LIST_enum): n->norm->Bl.count = 0; break; - case (LIST_column): - outflags |= MMAN_nl; - print_word(".TE"); - break; default: break; } - outflags |= MMAN_br; + outflags |= MMAN_PP | MMAN_nl; + outflags &= ~(MMAN_sp | MMAN_br); } static int @@ -856,9 +903,7 @@ static int pre_dl(DECL_ARGS) { - outflags |= MMAN_nl; - print_word(".RS 6n"); - outflags |= MMAN_nl; + print_line(".RS 6n", MMAN_nl); return(1); } @@ -866,9 +911,7 @@ static void post_dl(DECL_ARGS) { - outflags |= MMAN_nl; - print_word(".RE"); - outflags |= MMAN_nl; + print_line(".RE", MMAN_nl); } static int @@ -1070,28 +1113,25 @@ pre_it(DECL_ARGS) switch (n->type) { case (MDOC_HEAD): - outflags |= MMAN_nl; + outflags |= MMAN_PP | MMAN_nl; bln = n->parent->parent; + if (0 == bln->norm->Bl.comp || + (NULL == n->parent->prev && + NULL == bln->parent->prev)) + outflags |= MMAN_sp; + outflags &= ~MMAN_br; switch (bln->norm->Bl.type) { case (LIST_item): - if (bln->norm->Bl.comp) - outflags |= MMAN_br; - else - outflags |= MMAN_sp; return(0); case (LIST_inset): /* FALLTHROUGH */ case (LIST_diag): /* FALLTHROUGH */ case (LIST_ohang): - if (bln->norm->Bl.comp) - outflags |= MMAN_br; - else - outflags |= MMAN_sp; if (bln->norm->Bl.type == LIST_diag) - print_word(".B \""); + print_line(".B \"", 0); else - print_word(".R \""); + print_line(".R \"", 0); outflags &= ~MMAN_spc; return(1); case (LIST_bullet): @@ -1100,6 +1140,7 @@ pre_it(DECL_ARGS) /* FALLTHROUGH */ case (LIST_hyphen): print_width(bln->norm->Bl.width, NULL, 0); + TPremain = 0; outflags |= MMAN_nl; font_push('B'); if (LIST_bullet == bln->norm->Bl.type) @@ -1110,15 +1151,19 @@ pre_it(DECL_ARGS) break; case (LIST_enum): print_width(bln->norm->Bl.width, NULL, 0); + TPremain = 0; outflags |= MMAN_nl; print_count(&bln->norm->Bl.count); break; case (LIST_hang): print_width(bln->norm->Bl.width, n->child, 6); + TPremain = 0; break; case (LIST_tag): - print_width(bln->norm->Bl.width, NULL, 8); - break; + print_width(bln->norm->Bl.width, n->child, 0); + putchar('\n'); + outflags &= ~MMAN_spc; + return(1); default: return(1); } @@ -1205,13 +1250,22 @@ pre_li(DECL_ARGS) static int pre_nm(DECL_ARGS) { + char *name; if (MDOC_BLOCK == n->type) pre_syn(n); if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) return(1); - if (NULL == n->child && NULL == m->name) + name = n->child ? n->child->string : m->name; + if (NULL == name) return(0); + if (MDOC_HEAD == n->type) { + if (NULL == n->parent->prev) + outflags |= MMAN_sp; + print_block(".HP", 0); + printf(" %ldn", strlen(name) + 1); + outflags |= MMAN_nl; + } font_push('B'); if (NULL == n->child) print_word(m->name); @@ -1254,12 +1308,10 @@ static int pre_pp(DECL_ARGS) { - outflags |= MMAN_nl; - if (MDOC_It == n->parent->tok) - print_word(".sp"); - else - print_word(".PP"); - outflags |= MMAN_nl; + if (MDOC_It != n->parent->tok) + outflags |= MMAN_PP; + outflags |= MMAN_sp | MMAN_nl; + outflags &= ~MMAN_br; return(0); } @@ -1268,9 +1320,8 @@ pre_rs(DECL_ARGS) { if (SEC_SEE_ALSO == n->sec) { - outflags |= MMAN_nl; - print_word(".PP"); - outflags |= MMAN_nl; + outflags |= MMAN_PP | MMAN_sp | MMAN_nl; + outflags &= ~MMAN_br; } return(1); } @@ -1291,8 +1342,7 @@ static int pre_sp(DECL_ARGS) { - outflags |= MMAN_nl; - print_word(".sp"); + print_line(".sp", MMAN_nl); return(1); }