-/* $Id: mdoc_man.c,v 1.44 2012/11/18 19:34:19 schwarze Exp $ */
+/* $Id: mdoc_man.c,v 1.51 2013/06/02 18:16:57 schwarze Exp $ */
/*
- * Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012, 2013 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
static int cond_head(DECL_ARGS);
static void font_push(char);
static void font_pop(void);
+static void mid_it(void);
static void post__t(DECL_ARGS);
static void post_bd(DECL_ARGS);
static void post_bf(DECL_ARGS);
{ NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
{ NULL, NULL, NULL, NULL, NULL }, /* Db */
{ NULL, NULL, NULL, NULL, NULL }, /* Dc */
- { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */
- { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
+ { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
+ { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
{ NULL, NULL, NULL, NULL, NULL }, /* Ec */
{ NULL, NULL, NULL, NULL, NULL }, /* Ef */
{ NULL, pre_em, post_font, NULL, NULL }, /* Em */
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
{ cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
{ NULL, NULL, NULL, NULL, NULL }, /* Qc */
- { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
{ cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
{ NULL, NULL, NULL, NULL, NULL }, /* Re */
{ cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
{ NULL, NULL, NULL, NULL, NULL }, /* Sc */
- { cond_body, pre_enc, post_enc, "`", "'" }, /* So */
- { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
+ { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
{ NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
{ NULL, pre_em, post_font, NULL, NULL }, /* Sx */
{ NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
#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" */
-#define MMAN_PD (1 << 10) /* inter-paragraph spacing disabled */
+#define MMAN_Bk_susp (1 << 8) /* suspend this (after a macro) */
+#define MMAN_An_split (1 << 9) /* author mode is "split" */
+#define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
+#define MMAN_PD (1 << 11) /* inter-paragraph spacing disabled */
#define BL_STACK_MAX 32
*/
if (MMAN_spc_force & outflags || '\0' == s[0] ||
NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
- if (MMAN_Bk & outflags) {
+ if (MMAN_Bk & outflags &&
+ ! (MMAN_Bk_susp & outflags))
putchar('\\');
- putchar('~');
- } else
- putchar(' ');
+ putchar(' ');
if (TPremain)
TPremain--;
}
outflags |= MMAN_spc;
else
outflags &= ~MMAN_spc;
- outflags &= ~MMAN_spc_force;
+ outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
for ( ; *s; s++) {
switch (*s) {
case (ASCII_NBRSP):
- printf("\\~");
+ printf("\\ ");
break;
case (ASCII_HYPH):
putchar('-');
print_line(".PD", 0);
outflags &= ~MMAN_PD;
}
- } else if (! (MMAN_PD & outflags)) {
- print_line(".PD 0", 0);
- outflags |= MMAN_PD;
- }
+ } else if (! (MMAN_PD & outflags))
+ print_line(".PD 0", MMAN_PD);
outflags |= MMAN_nl;
print_word(s);
- outflags |= newflags;
+ outflags |= MMAN_Bk_susp | newflags;
}
static void
struct roffsu su;
size_t sz;
+ print_line(".RS", MMAN_Bk_susp);
+
/* Convert v into a number (of characters). */
if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
sz = 0;
* in terms of different units.
*/
print_word(v);
+ outflags |= MMAN_nl;
return;
}
} else
snprintf(buf, sizeof(buf), "%ldn", sz);
print_word(buf);
+ outflags |= MMAN_nl;
}
+/*
+ * Set up the indentation for a list item; used from pre_it().
+ */
void
print_width(const char *v, const struct mdoc_node *child, size_t defsz)
{
chsz = (NULL != child && MDOC_TEXT == child->type) ?
strlen(child->string) : 0;
- /*
- * If we are inside an enclosing list,
- * preserve its indentation.
- */
- if (Bl_stack_len && Bl_stack[Bl_stack_len - 1]) {
- print_line(".RS", 0);
- snprintf(buf, sizeof(buf), "%ldn",
- Bl_stack[Bl_stack_len - 1]);
- print_word(buf);
- }
+ /* Maybe we are inside an enclosing list? */
+ mid_it();
/*
* Save our own indentation,
meta = mdoc_meta(mdoc);
n = mdoc_node(mdoc);
- printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
+ printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
meta->title, meta->msec, meta->date,
meta->os, meta->vol);
+ /* Disable hyphenation and if nroff, disable justification. */
+ printf(".nh\n.if n .ad l");
+
outflags = MMAN_nl | MMAN_Sm;
if (0 == fontqueue.size) {
fontqueue.size = 8;
const struct mdoc_node *prev, *sub;
const struct manact *act;
int cond, do_sub;
-
+
/*
* Break the line if we were parsed subsequent the current node.
* This makes the page structure be more consistent.
pre_sect(DECL_ARGS)
{
- if (MDOC_HEAD != n->type)
- return(1);
- outflags |= MMAN_sp;
- print_block(manacts[n->tok].prefix, 0);
- print_word("");
- putchar('\"');
- outflags &= ~MMAN_spc;
+ switch (n->type) {
+ case (MDOC_HEAD):
+ outflags |= MMAN_sp;
+ print_block(manacts[n->tok].prefix, 0);
+ print_word("");
+ putchar('\"');
+ outflags &= ~MMAN_spc;
+ break;
+ case (MDOC_BODY):
+ if (MDOC_Sh == n->tok) {
+ if (MDOC_SYNPRETTY & n->flags)
+ outflags |= MMAN_Bk;
+ else
+ outflags &= ~MMAN_Bk;
+ }
+ break;
+ default:
+ break;
+ }
return(1);
}
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);
}
static void
post_bd(DECL_ARGS)
{
- char buf[24];
/* Close out this display. */
print_line(".RE", MMAN_nl);
DISP_literal == n->norm->Bd.type)
print_line(".fi", MMAN_nl);
- /*
- * If we are inside an enclosing list and the current
- * list item is not yet finished, restore the correct
- * indentation for what remains of that item.
- */
- if (NULL != n->parent->next &&
- Bl_stack_len && Bl_stack[Bl_stack_len - 1]) {
- print_line(".RS", 0);
- snprintf(buf, sizeof(buf), "%ldn",
- Bl_stack[Bl_stack_len - 1]);
- print_word(buf);
- /* Remeber to close out this .RS block later. */
- Bl_stack_post[Bl_stack_len - 1] = 1;
- }
+ /* Maybe we are inside an enclosing list? */
+ if (NULL != n->parent->next)
+ mid_it();
}
static int
post_bk(DECL_ARGS)
{
- if (MDOC_BODY == n->type)
+ if (MDOC_BODY == n->type && ! (MDOC_SYNPRETTY & n->flags))
outflags &= ~MMAN_Bk;
}
{
size_t icol;
+ /*
+ * print_offs() will increase the -offset to account for
+ * a possible enclosing .It, but any enclosed .It blocks
+ * just nest and do not add up their indentation.
+ */
+ if (n->norm->Bl.offs) {
+ print_offs(n->norm->Bl.offs);
+ Bl_stack[Bl_stack_len++] = 0;
+ }
+
switch (n->norm->Bl.type) {
case (LIST_enum):
n->norm->Bl.count = 0;
default:
break;
}
- outflags |= MMAN_PP | MMAN_nl;
- outflags &= ~(MMAN_sp | MMAN_br);
+
+ if (n->norm->Bl.offs) {
+ print_line(".RE", MMAN_nl);
+ assert(Bl_stack_len);
+ Bl_stack_len--;
+ assert(0 == Bl_stack[Bl_stack_len]);
+ } else {
+ outflags |= MMAN_PP | MMAN_nl;
+ outflags &= ~(MMAN_sp | MMAN_br);
+ }
+
+ /* Maybe we are inside an enclosing list? */
+ if (NULL != n->parent->next)
+ mid_it();
+
}
static int
pre_dl(DECL_ARGS)
{
- print_line(".RS 6n", MMAN_nl);
+ print_offs("6n");
return(1);
}
{
print_line(".RE", MMAN_nl);
+
+ /* Maybe we are inside an enclosing list? */
+ if (NULL != n->parent->next)
+ mid_it();
}
static int
{
font_push('B');
- print_word("-");
+ print_word("\\-");
outflags &= ~MMAN_spc;
return(1);
}
return(1);
}
+/*
+ * This function is called after closing out an indented block.
+ * If we are inside an enclosing list, restore its indentation.
+ */
+static void
+mid_it(void)
+{
+ char buf[24];
+
+ /* Nothing to do outside a list. */
+ if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
+ return;
+
+ /* The indentation has already been set up. */
+ if (Bl_stack_post[Bl_stack_len - 1])
+ return;
+
+ /* Restore the indentation of the enclosing list. */
+ print_line(".RS", MMAN_Bk_susp);
+ snprintf(buf, sizeof(buf), "%ldn", Bl_stack[Bl_stack_len - 1]);
+ print_word(buf);
+
+ /* Remeber to close out this .RS block later. */
+ Bl_stack_post[Bl_stack_len - 1] = 1;
+}
+
static void
post_it(DECL_ARGS)
{
/*
* Our indentation had to be restored
- * after a child display.
+ * after a child display or child list.
* Close out that indentation block now.
*/
if (Bl_stack_post[Bl_stack_len]) {
print_line(".RE", MMAN_nl);
Bl_stack_post[Bl_stack_len] = 0;
}
-
- /*
- * We are inside an enclosing list.
- * Restore the indentation of that list.
- */
- if (Bl_stack_len && Bl_stack[Bl_stack_len - 1])
- print_line(".RE", MMAN_nl);
break;
case (LIST_column):
if (NULL != n->next) {
if (NULL == n->child)
return(0);
outflags &= ~MMAN_spc;
- print_word("\\~");
+ print_word("\\ ");
outflags &= ~MMAN_spc;
return(1);
}