Print this page
Update to 1.12.3.

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/mdoc_man.c
          +++ new/usr/src/cmd/mandoc/mdoc_man.c
   1      -/*      $Id: mdoc_man.c,v 1.9 2011/10/24 21:47:59 schwarze Exp $ */
        1 +/*      $Id: mdoc_man.c,v 1.57 2013/12/25 22:00:45 schwarze Exp $ */
   2    2  /*
   3      - * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
        3 + * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
   4    4   *
   5    5   * Permission to use, copy, modify, and distribute this software for any
   6    6   * purpose with or without fee is hereby granted, provided that the above
   7    7   * copyright notice and this permission notice appear in all copies.
   8    8   *
   9    9   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10   10   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11   11   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12   12   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13   13   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14   14   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  15   15   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16   16   */
  17   17  #ifdef HAVE_CONFIG_H
  18   18  #include "config.h"
  19   19  #endif
  20   20  
       21 +#include <assert.h>
  21   22  #include <stdio.h>
  22   23  #include <string.h>
  23   24  
  24   25  #include "mandoc.h"
       26 +#include "out.h"
  25   27  #include "man.h"
  26   28  #include "mdoc.h"
  27   29  #include "main.h"
  28   30  
  29      -#define DECL_ARGS const struct mdoc_meta *m, \
  30      -                  const struct mdoc_node *n, \
  31      -                  struct mman *mm
       31 +#define DECL_ARGS const struct mdoc_meta *meta, \
       32 +                  const struct mdoc_node *n
  32   33  
  33      -struct  mman {
  34      -        int               need_space; /* next word needs prior ws */
  35      -        int               need_nl; /* next word needs prior nl */
  36      -};
  37      -
  38   34  struct  manact {
  39   35          int             (*cond)(DECL_ARGS); /* DON'T run actions */
  40   36          int             (*pre)(DECL_ARGS); /* pre-node action */
  41   37          void            (*post)(DECL_ARGS); /* post-node action */
  42   38          const char       *prefix; /* pre-node string constant */
  43   39          const char       *suffix; /* post-node string constant */
  44   40  };
  45   41  
  46   42  static  int       cond_body(DECL_ARGS);
  47   43  static  int       cond_head(DECL_ARGS);
       44 +static  void      font_push(char);
       45 +static  void      font_pop(void);
       46 +static  void      mid_it(void);
       47 +static  void      post__t(DECL_ARGS);
  48   48  static  void      post_bd(DECL_ARGS);
       49 +static  void      post_bf(DECL_ARGS);
       50 +static  void      post_bk(DECL_ARGS);
       51 +static  void      post_bl(DECL_ARGS);
  49   52  static  void      post_dl(DECL_ARGS);
  50   53  static  void      post_enc(DECL_ARGS);
       54 +static  void      post_eo(DECL_ARGS);
       55 +static  void      post_fa(DECL_ARGS);
       56 +static  void      post_fd(DECL_ARGS);
       57 +static  void      post_fl(DECL_ARGS);
       58 +static  void      post_fn(DECL_ARGS);
       59 +static  void      post_fo(DECL_ARGS);
       60 +static  void      post_font(DECL_ARGS);
       61 +static  void      post_in(DECL_ARGS);
       62 +static  void      post_it(DECL_ARGS);
       63 +static  void      post_lb(DECL_ARGS);
  51   64  static  void      post_nm(DECL_ARGS);
  52   65  static  void      post_percent(DECL_ARGS);
  53   66  static  void      post_pf(DECL_ARGS);
  54   67  static  void      post_sect(DECL_ARGS);
  55   68  static  void      post_sp(DECL_ARGS);
       69 +static  void      post_vt(DECL_ARGS);
       70 +static  int       pre__t(DECL_ARGS);
       71 +static  int       pre_an(DECL_ARGS);
  56   72  static  int       pre_ap(DECL_ARGS);
  57   73  static  int       pre_bd(DECL_ARGS);
       74 +static  int       pre_bf(DECL_ARGS);
       75 +static  int       pre_bk(DECL_ARGS);
       76 +static  int       pre_bl(DECL_ARGS);
  58   77  static  int       pre_br(DECL_ARGS);
  59   78  static  int       pre_bx(DECL_ARGS);
  60   79  static  int       pre_dl(DECL_ARGS);
  61   80  static  int       pre_enc(DECL_ARGS);
       81 +static  int       pre_em(DECL_ARGS);
       82 +static  int       pre_fa(DECL_ARGS);
       83 +static  int       pre_fd(DECL_ARGS);
       84 +static  int       pre_fl(DECL_ARGS);
       85 +static  int       pre_fn(DECL_ARGS);
       86 +static  int       pre_fo(DECL_ARGS);
       87 +static  int       pre_ft(DECL_ARGS);
       88 +static  int       pre_in(DECL_ARGS);
  62   89  static  int       pre_it(DECL_ARGS);
       90 +static  int       pre_lk(DECL_ARGS);
       91 +static  int       pre_li(DECL_ARGS);
  63   92  static  int       pre_nm(DECL_ARGS);
       93 +static  int       pre_no(DECL_ARGS);
  64   94  static  int       pre_ns(DECL_ARGS);
  65   95  static  int       pre_pp(DECL_ARGS);
       96 +static  int       pre_rs(DECL_ARGS);
       97 +static  int       pre_sm(DECL_ARGS);
  66   98  static  int       pre_sp(DECL_ARGS);
  67   99  static  int       pre_sect(DECL_ARGS);
      100 +static  int       pre_sy(DECL_ARGS);
      101 +static  void      pre_syn(const struct mdoc_node *);
      102 +static  int       pre_vt(DECL_ARGS);
  68  103  static  int       pre_ux(DECL_ARGS);
  69  104  static  int       pre_xr(DECL_ARGS);
  70      -static  void      print_word(struct mman *, const char *);
      105 +static  void      print_word(const char *);
      106 +static  void      print_line(const char *, int);
      107 +static  void      print_block(const char *, int);
      108 +static  void      print_offs(const char *);
      109 +static  void      print_width(const char *,
      110 +                                const struct mdoc_node *, size_t);
      111 +static  void      print_count(int *);
  71  112  static  void      print_node(DECL_ARGS);
  72  113  
  73  114  static  const struct manact manacts[MDOC_MAX + 1] = {
  74  115          { NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
  75  116          { NULL, NULL, NULL, NULL, NULL }, /* Dd */
  76  117          { NULL, NULL, NULL, NULL, NULL }, /* Dt */
  77  118          { NULL, NULL, NULL, NULL, NULL }, /* Os */
  78  119          { NULL, pre_sect, post_sect, ".SH", NULL }, /* Sh */
  79  120          { NULL, pre_sect, post_sect, ".SS", NULL }, /* Ss */
  80  121          { NULL, pre_pp, NULL, NULL, NULL }, /* Pp */
  81  122          { cond_body, pre_dl, post_dl, NULL, NULL }, /* D1 */
  82  123          { cond_body, pre_dl, post_dl, NULL, NULL }, /* Dl */
  83  124          { cond_body, pre_bd, post_bd, NULL, NULL }, /* Bd */
  84  125          { NULL, NULL, NULL, NULL, NULL }, /* Ed */
  85      -        { NULL, NULL, NULL, NULL, NULL }, /* Bl */
      126 +        { cond_body, pre_bl, post_bl, NULL, NULL }, /* Bl */
  86  127          { NULL, NULL, NULL, NULL, NULL }, /* El */
  87      -        { NULL, pre_it, NULL, NULL, NULL }, /* _It */
  88      -        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ad */
  89      -        { NULL, NULL, NULL, NULL, NULL }, /* _An */
  90      -        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Ar */
  91      -        { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cd */
  92      -        { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Cm */
  93      -        { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Dv */
  94      -        { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Er */
  95      -        { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Ev */
      128 +        { NULL, pre_it, post_it, NULL, NULL }, /* It */
      129 +        { NULL, pre_em, post_font, NULL, NULL }, /* Ad */
      130 +        { NULL, pre_an, NULL, NULL, NULL }, /* An */
      131 +        { NULL, pre_em, post_font, NULL, NULL }, /* Ar */
      132 +        { NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
      133 +        { NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
      134 +        { NULL, pre_li, post_font, NULL, NULL }, /* Dv */
      135 +        { NULL, pre_li, post_font, NULL, NULL }, /* Er */
      136 +        { NULL, pre_li, post_font, NULL, NULL }, /* Ev */
  96  137          { NULL, pre_enc, post_enc, "The \\fB",
  97  138              "\\fP\nutility exits 0 on success, and >0 if an error occurs."
  98  139              }, /* Ex */
  99      -        { NULL, NULL, NULL, NULL, NULL }, /* _Fa */
 100      -        { NULL, NULL, NULL, NULL, NULL }, /* _Fd */
 101      -        { NULL, pre_enc, post_enc, "\\fB-", "\\fP" }, /* Fl */
 102      -        { NULL, NULL, NULL, NULL, NULL }, /* _Fn */
 103      -        { NULL, NULL, NULL, NULL, NULL }, /* _Ft */
 104      -        { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ic */
 105      -        { NULL, NULL, NULL, NULL, NULL }, /* _In */
 106      -        { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Li */
      140 +        { NULL, pre_fa, post_fa, NULL, NULL }, /* Fa */
      141 +        { NULL, pre_fd, post_fd, NULL, NULL }, /* Fd */
      142 +        { NULL, pre_fl, post_fl, NULL, NULL }, /* Fl */
      143 +        { NULL, pre_fn, post_fn, NULL, NULL }, /* Fn */
      144 +        { NULL, pre_ft, post_font, NULL, NULL }, /* Ft */
      145 +        { NULL, pre_sy, post_font, NULL, NULL }, /* Ic */
      146 +        { NULL, pre_in, post_in, NULL, NULL }, /* In */
      147 +        { NULL, pre_li, post_font, NULL, NULL }, /* Li */
 107  148          { cond_head, pre_enc, NULL, "\\- ", NULL }, /* Nd */
 108  149          { NULL, pre_nm, post_nm, NULL, NULL }, /* Nm */
 109  150          { cond_body, pre_enc, post_enc, "[", "]" }, /* Op */
 110  151          { NULL, NULL, NULL, NULL, NULL }, /* Ot */
 111      -        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Pa */
      152 +        { NULL, pre_em, post_font, NULL, NULL }, /* Pa */
 112  153          { NULL, pre_enc, post_enc, "The \\fB",
 113  154                  "\\fP\nfunction returns the value 0 if successful;\n"
 114  155                  "otherwise the value -1 is returned and the global\n"
 115  156                  "variable \\fIerrno\\fP is set to indicate the error."
 116  157                  }, /* Rv */
 117  158          { NULL, NULL, NULL, NULL, NULL }, /* St */
 118      -        { NULL, NULL, NULL, NULL, NULL }, /* _Va */
 119      -        { NULL, NULL, NULL, NULL, NULL }, /* _Vt */
      159 +        { NULL, pre_em, post_font, NULL, NULL }, /* Va */
      160 +        { NULL, pre_vt, post_vt, NULL, NULL }, /* Vt */
 120  161          { NULL, pre_xr, NULL, NULL, NULL }, /* Xr */
 121      -        { NULL, NULL, post_percent, NULL, NULL }, /* _%A */
 122      -        { NULL, NULL, NULL, NULL, NULL }, /* _%B */
 123      -        { NULL, NULL, post_percent, NULL, NULL }, /* _%D */
 124      -        { NULL, NULL, NULL, NULL, NULL }, /* _%I */
 125      -        { NULL, pre_enc, post_percent, "\\fI", "\\fP" }, /* %J */
 126      -        { NULL, NULL, NULL, NULL, NULL }, /* _%N */
 127      -        { NULL, NULL, NULL, NULL, NULL }, /* _%O */
 128      -        { NULL, NULL, NULL, NULL, NULL }, /* _%P */
 129      -        { NULL, NULL, NULL, NULL, NULL }, /* _%R */
 130      -        { NULL, pre_enc, post_percent, "\"", "\"" }, /* %T */
 131      -        { NULL, NULL, NULL, NULL, NULL }, /* _%V */
      162 +        { NULL, NULL, post_percent, NULL, NULL }, /* %A */
      163 +        { NULL, pre_em, post_percent, NULL, NULL }, /* %B */
      164 +        { NULL, NULL, post_percent, NULL, NULL }, /* %D */
      165 +        { NULL, pre_em, post_percent, NULL, NULL }, /* %I */
      166 +        { NULL, pre_em, post_percent, NULL, NULL }, /* %J */
      167 +        { NULL, NULL, post_percent, NULL, NULL }, /* %N */
      168 +        { NULL, NULL, post_percent, NULL, NULL }, /* %O */
      169 +        { NULL, NULL, post_percent, NULL, NULL }, /* %P */
      170 +        { NULL, NULL, post_percent, NULL, NULL }, /* %R */
      171 +        { NULL, pre__t, post__t, NULL, NULL }, /* %T */
      172 +        { NULL, NULL, post_percent, NULL, NULL }, /* %V */
 132  173          { NULL, NULL, NULL, NULL, NULL }, /* Ac */
 133  174          { cond_body, pre_enc, post_enc, "<", ">" }, /* Ao */
 134  175          { cond_body, pre_enc, post_enc, "<", ">" }, /* Aq */
 135  176          { NULL, NULL, NULL, NULL, NULL }, /* At */
 136  177          { NULL, NULL, NULL, NULL, NULL }, /* Bc */
 137      -        { NULL, NULL, NULL, NULL, NULL }, /* _Bf */
      178 +        { NULL, pre_bf, post_bf, NULL, NULL }, /* Bf */
 138  179          { cond_body, pre_enc, post_enc, "[", "]" }, /* Bo */
 139  180          { cond_body, pre_enc, post_enc, "[", "]" }, /* Bq */
 140  181          { NULL, pre_ux, NULL, "BSD/OS", NULL }, /* Bsx */
 141  182          { NULL, pre_bx, NULL, NULL, NULL }, /* Bx */
 142  183          { NULL, NULL, NULL, NULL, NULL }, /* Db */
 143  184          { NULL, NULL, NULL, NULL, NULL }, /* Dc */
 144      -        { cond_body, pre_enc, post_enc, "``", "''" }, /* Do */
 145      -        { cond_body, pre_enc, post_enc, "``", "''" }, /* Dq */
 146      -        { NULL, NULL, NULL, NULL, NULL }, /* _Ec */
 147      -        { NULL, NULL, NULL, NULL, NULL }, /* _Ef */
 148      -        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Em */
 149      -        { NULL, NULL, NULL, NULL, NULL }, /* _Eo */
      185 +        { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Do */
      186 +        { cond_body, pre_enc, post_enc, "\\(lq", "\\(rq" }, /* Dq */
      187 +        { NULL, NULL, NULL, NULL, NULL }, /* Ec */
      188 +        { NULL, NULL, NULL, NULL, NULL }, /* Ef */
      189 +        { NULL, pre_em, post_font, NULL, NULL }, /* Em */
      190 +        { NULL, NULL, post_eo, NULL, NULL }, /* Eo */
 150  191          { NULL, pre_ux, NULL, "FreeBSD", NULL }, /* Fx */
 151      -        { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Ms */
 152      -        { NULL, NULL, NULL, NULL, NULL }, /* No */
      192 +        { NULL, pre_sy, post_font, NULL, NULL }, /* Ms */
      193 +        { NULL, pre_no, NULL, NULL, NULL }, /* No */
 153  194          { NULL, pre_ns, NULL, NULL, NULL }, /* Ns */
 154  195          { NULL, pre_ux, NULL, "NetBSD", NULL }, /* Nx */
 155  196          { NULL, pre_ux, NULL, "OpenBSD", NULL }, /* Ox */
 156  197          { NULL, NULL, NULL, NULL, NULL }, /* Pc */
 157  198          { NULL, NULL, post_pf, NULL, NULL }, /* Pf */
 158  199          { cond_body, pre_enc, post_enc, "(", ")" }, /* Po */
 159  200          { cond_body, pre_enc, post_enc, "(", ")" }, /* Pq */
 160  201          { NULL, NULL, NULL, NULL, NULL }, /* Qc */
 161      -        { cond_body, pre_enc, post_enc, "`", "'" }, /* Ql */
      202 +        { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Ql */
 162  203          { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qo */
 163  204          { cond_body, pre_enc, post_enc, "\"", "\"" }, /* Qq */
 164  205          { NULL, NULL, NULL, NULL, NULL }, /* Re */
 165      -        { cond_body, pre_pp, NULL, NULL, NULL }, /* Rs */
      206 +        { cond_body, pre_rs, NULL, NULL, NULL }, /* Rs */
 166  207          { NULL, NULL, NULL, NULL, NULL }, /* Sc */
 167      -        { cond_body, pre_enc, post_enc, "`", "'" }, /* So */
 168      -        { cond_body, pre_enc, post_enc, "`", "'" }, /* Sq */
 169      -        { NULL, NULL, NULL, NULL, NULL }, /* _Sm */
 170      -        { NULL, pre_enc, post_enc, "\\fI", "\\fP" }, /* Sx */
 171      -        { NULL, pre_enc, post_enc, "\\fB", "\\fP" }, /* Sy */
 172      -        { NULL, pre_enc, post_enc, "\\fR", "\\fP" }, /* Tn */
      208 +        { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* So */
      209 +        { cond_body, pre_enc, post_enc, "\\(oq", "\\(cq" }, /* Sq */
      210 +        { NULL, pre_sm, NULL, NULL, NULL }, /* Sm */
      211 +        { NULL, pre_em, post_font, NULL, NULL }, /* Sx */
      212 +        { NULL, pre_sy, post_font, NULL, NULL }, /* Sy */
      213 +        { NULL, pre_li, post_font, NULL, NULL }, /* Tn */
 173  214          { NULL, pre_ux, NULL, "UNIX", NULL }, /* Ux */
 174      -        { NULL, NULL, NULL, NULL, NULL }, /* _Xc */
 175      -        { NULL, NULL, NULL, NULL, NULL }, /* _Xo */
 176      -        { NULL, NULL, NULL, NULL, NULL }, /* _Fo */
 177      -        { NULL, NULL, NULL, NULL, NULL }, /* _Fc */
      215 +        { NULL, NULL, NULL, NULL, NULL }, /* Xc */
      216 +        { NULL, NULL, NULL, NULL, NULL }, /* Xo */
      217 +        { NULL, pre_fo, post_fo, NULL, NULL }, /* Fo */
      218 +        { NULL, NULL, NULL, NULL, NULL }, /* Fc */
 178  219          { cond_body, pre_enc, post_enc, "[", "]" }, /* Oo */
 179  220          { NULL, NULL, NULL, NULL, NULL }, /* Oc */
 180      -        { NULL, NULL, NULL, NULL, NULL }, /* _Bk */
 181      -        { NULL, NULL, NULL, NULL, NULL }, /* _Ek */
      221 +        { NULL, pre_bk, post_bk, NULL, NULL }, /* Bk */
      222 +        { NULL, NULL, NULL, NULL, NULL }, /* Ek */
 182  223          { NULL, pre_ux, NULL, "is currently in beta test.", NULL }, /* Bt */
 183  224          { NULL, NULL, NULL, NULL, NULL }, /* Hf */
 184  225          { NULL, NULL, NULL, NULL, NULL }, /* Fr */
 185  226          { NULL, pre_ux, NULL, "currently under development.", NULL }, /* Ud */
 186      -        { NULL, NULL, NULL, NULL, NULL }, /* _Lb */
      227 +        { NULL, NULL, post_lb, NULL, NULL }, /* Lb */
 187  228          { NULL, pre_pp, NULL, NULL, NULL }, /* Lp */
 188      -        { NULL, NULL, NULL, NULL, NULL }, /* _Lk */
 189      -        { NULL, NULL, NULL, NULL, NULL }, /* _Mt */
      229 +        { NULL, pre_lk, NULL, NULL, NULL }, /* Lk */
      230 +        { NULL, pre_em, post_font, NULL, NULL }, /* Mt */
 190  231          { cond_body, pre_enc, post_enc, "{", "}" }, /* Brq */
 191  232          { cond_body, pre_enc, post_enc, "{", "}" }, /* Bro */
 192  233          { NULL, NULL, NULL, NULL, NULL }, /* Brc */
 193      -        { NULL, NULL, NULL, NULL, NULL }, /* _%C */
 194      -        { NULL, NULL, NULL, NULL, NULL }, /* _Es */
 195      -        { NULL, NULL, NULL, NULL, NULL }, /* _En */
      234 +        { NULL, NULL, post_percent, NULL, NULL }, /* %C */
      235 +        { NULL, NULL, NULL, NULL, NULL }, /* Es */
      236 +        { NULL, NULL, NULL, NULL, NULL }, /* En */
 196  237          { NULL, pre_ux, NULL, "DragonFly", NULL }, /* Dx */
 197      -        { NULL, NULL, NULL, NULL, NULL }, /* _%Q */
      238 +        { NULL, NULL, post_percent, NULL, NULL }, /* %Q */
 198  239          { NULL, pre_br, NULL, NULL, NULL }, /* br */
 199  240          { NULL, pre_sp, post_sp, NULL, NULL }, /* sp */
 200      -        { NULL, NULL, NULL, NULL, NULL }, /* _%U */
 201      -        { NULL, NULL, NULL, NULL, NULL }, /* _Ta */
      241 +        { NULL, NULL, post_percent, NULL, NULL }, /* %U */
      242 +        { NULL, NULL, NULL, NULL, NULL }, /* Ta */
 202  243          { NULL, NULL, NULL, NULL, NULL }, /* ROOT */
 203  244  };
 204  245  
      246 +static  int             outflags;
      247 +#define MMAN_spc        (1 << 0)  /* blank character before next word */
      248 +#define MMAN_spc_force  (1 << 1)  /* even before trailing punctuation */
      249 +#define MMAN_nl         (1 << 2)  /* break man(7) code line */
      250 +#define MMAN_br         (1 << 3)  /* break output line */
      251 +#define MMAN_sp         (1 << 4)  /* insert a blank output line */
      252 +#define MMAN_PP         (1 << 5)  /* reset indentation etc. */
      253 +#define MMAN_Sm         (1 << 6)  /* horizontal spacing mode */
      254 +#define MMAN_Bk         (1 << 7)  /* word keep mode */
      255 +#define MMAN_Bk_susp    (1 << 8)  /* suspend this (after a macro) */
      256 +#define MMAN_An_split   (1 << 9)  /* author mode is "split" */
      257 +#define MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
      258 +#define MMAN_PD         (1 << 11) /* inter-paragraph spacing disabled */
      259 +#define MMAN_nbrword    (1 << 12) /* do not break the next word */
      260 +
      261 +#define BL_STACK_MAX    32
      262 +
      263 +static  size_t          Bl_stack[BL_STACK_MAX];  /* offsets [chars] */
      264 +static  int             Bl_stack_post[BL_STACK_MAX];  /* add final .RE */
      265 +static  int             Bl_stack_len;  /* number of nested Bl blocks */
      266 +static  int             TPremain;  /* characters before tag is full */
      267 +
      268 +static  struct {
      269 +        char    *head;
      270 +        char    *tail;
      271 +        size_t   size;
      272 +}       fontqueue;
      273 +
 205  274  static void
 206      -print_word(struct mman *mm, const char *s)
      275 +font_push(char newfont)
 207  276  {
 208  277  
 209      -        if (mm->need_nl) {
      278 +        if (fontqueue.head + fontqueue.size <= ++fontqueue.tail) {
      279 +                fontqueue.size += 8;
      280 +                fontqueue.head = mandoc_realloc(fontqueue.head,
      281 +                                fontqueue.size);
      282 +        }
      283 +        *fontqueue.tail = newfont;
      284 +        print_word("");
      285 +        printf("\\f");
      286 +        putchar(newfont);
      287 +        outflags &= ~MMAN_spc;
      288 +}
      289 +
      290 +static void
      291 +font_pop(void)
      292 +{
      293 +
      294 +        if (fontqueue.tail > fontqueue.head)
      295 +                fontqueue.tail--;
      296 +        outflags &= ~MMAN_spc;
      297 +        print_word("");
      298 +        printf("\\f");
      299 +        putchar(*fontqueue.tail);
      300 +}
      301 +
      302 +static void
      303 +print_word(const char *s)
      304 +{
      305 +
      306 +        if ((MMAN_PP | MMAN_sp | MMAN_br | MMAN_nl) & outflags) {
 210  307                  /* 
 211  308                   * If we need a newline, print it now and start afresh.
 212  309                   */
 213      -                putchar('\n');
 214      -                mm->need_space = 0;
 215      -                mm->need_nl = 0;
 216      -        } else if (mm->need_space && '\0' != s[0])
      310 +                if (MMAN_PP & outflags) {
      311 +                        if (MMAN_sp & outflags) {
      312 +                                if (MMAN_PD & outflags) {
      313 +                                        printf("\n.PD");
      314 +                                        outflags &= ~MMAN_PD;
      315 +                                }
      316 +                        } else if ( ! (MMAN_PD & outflags)) {
      317 +                                printf("\n.PD 0");
      318 +                                outflags |= MMAN_PD;
      319 +                        }
      320 +                        printf("\n.PP\n");
      321 +                } else if (MMAN_sp & outflags)
      322 +                        printf("\n.sp\n");
      323 +                else if (MMAN_br & outflags)
      324 +                        printf("\n.br\n");
      325 +                else if (MMAN_nl & outflags)
      326 +                        putchar('\n');
      327 +                outflags &= ~(MMAN_PP|MMAN_sp|MMAN_br|MMAN_nl|MMAN_spc);
      328 +                if (1 == TPremain)
      329 +                        printf(".br\n");
      330 +                TPremain = 0;
      331 +        } else if (MMAN_spc & outflags) {
 217  332                  /*
 218      -                 * If we need a space, only print it before
 219      -                 * (1) a nonzero length word;
 220      -                 * (2) a word that is non-punctuation; and
 221      -                 * (3) if punctuation, non-terminating puncutation.
      333 +                 * If we need a space, only print it if
      334 +                 * (1) it is forced by `No' or
      335 +                 * (2) what follows is not terminating punctuation or
      336 +                 * (3) what follows is longer than one character.
 222  337                   */
 223      -                if (NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1])
      338 +                if (MMAN_spc_force & outflags || '\0' == s[0] ||
      339 +                    NULL == strchr(".,:;)]?!", s[0]) || '\0' != s[1]) {
      340 +                        if (MMAN_Bk & outflags &&
      341 +                            ! (MMAN_Bk_susp & outflags))
      342 +                                putchar('\\');
 224  343                          putchar(' ');
      344 +                        if (TPremain)
      345 +                                TPremain--;
      346 +                }
      347 +        }
 225  348  
 226  349          /*
 227  350           * Reassign needing space if we're not following opening
 228  351           * punctuation.
 229  352           */
 230      -        mm->need_space = 
 231      -                ('(' != s[0] && '[' != s[0]) || '\0' != s[1];
      353 +        if (MMAN_Sm & outflags && ('\0' == s[0] ||
      354 +            (('(' != s[0] && '[' != s[0]) || '\0' != s[1])))
      355 +                outflags |= MMAN_spc;
      356 +        else
      357 +                outflags &= ~MMAN_spc;
      358 +        outflags &= ~(MMAN_spc_force | MMAN_Bk_susp);
 232  359  
 233  360          for ( ; *s; s++) {
 234  361                  switch (*s) {
 235  362                  case (ASCII_NBRSP):
 236      -                        printf("\\~");
      363 +                        printf("\\ ");
 237  364                          break;
 238  365                  case (ASCII_HYPH):
 239  366                          putchar('-');
 240  367                          break;
      368 +                case (' '):
      369 +                        if (MMAN_nbrword & outflags) {
      370 +                                printf("\\ ");
      371 +                                break;
      372 +                        }
      373 +                        /* FALLTHROUGH */
 241  374                  default:
 242  375                          putchar((unsigned char)*s);
 243  376                          break;
 244  377                  }
      378 +                if (TPremain)
      379 +                        TPremain--;
 245  380          }
      381 +        outflags &= ~MMAN_nbrword;
 246  382  }
 247  383  
      384 +static void
      385 +print_line(const char *s, int newflags)
      386 +{
      387 +
      388 +        outflags &= ~MMAN_br;
      389 +        outflags |= MMAN_nl;
      390 +        print_word(s);
      391 +        outflags |= newflags;
      392 +}
      393 +
      394 +static void
      395 +print_block(const char *s, int newflags)
      396 +{
      397 +
      398 +        outflags &= ~MMAN_PP;
      399 +        if (MMAN_sp & outflags) {
      400 +                outflags &= ~(MMAN_sp | MMAN_br);
      401 +                if (MMAN_PD & outflags) {
      402 +                        print_line(".PD", 0);
      403 +                        outflags &= ~MMAN_PD;
      404 +                }
      405 +        } else if (! (MMAN_PD & outflags))
      406 +                print_line(".PD 0", MMAN_PD);
      407 +        outflags |= MMAN_nl;
      408 +        print_word(s);
      409 +        outflags |= MMAN_Bk_susp | newflags;
      410 +}
      411 +
      412 +static void
      413 +print_offs(const char *v)
      414 +{
      415 +        char              buf[24];
      416 +        struct roffsu     su;
      417 +        size_t            sz;
      418 +
      419 +        print_line(".RS", MMAN_Bk_susp);
      420 +
      421 +        /* Convert v into a number (of characters). */
      422 +        if (NULL == v || '\0' == *v || 0 == strcmp(v, "left"))
      423 +                sz = 0;
      424 +        else if (0 == strcmp(v, "indent"))
      425 +                sz = 6;
      426 +        else if (0 == strcmp(v, "indent-two"))
      427 +                sz = 12;
      428 +        else if (a2roffsu(v, &su, SCALE_MAX)) {
      429 +                if (SCALE_EN == su.unit)
      430 +                        sz = su.scale;
      431 +                else {
      432 +                        /*
      433 +                         * XXX
      434 +                         * If we are inside an enclosing list,
      435 +                         * there is no easy way to add the two
      436 +                         * indentations because they are provided
      437 +                         * in terms of different units.
      438 +                         */
      439 +                        print_word(v);
      440 +                        outflags |= MMAN_nl;
      441 +                        return;
      442 +                }
      443 +        } else
      444 +                sz = strlen(v);
      445 +
      446 +        /*
      447 +         * We are inside an enclosing list.
      448 +         * Add the two indentations.
      449 +         */
      450 +        if (Bl_stack_len)
      451 +                sz += Bl_stack[Bl_stack_len - 1];
      452 +
      453 +        snprintf(buf, sizeof(buf), "%zun", sz);
      454 +        print_word(buf);
      455 +        outflags |= MMAN_nl;
      456 +}
      457 +
      458 +/*
      459 + * Set up the indentation for a list item; used from pre_it().
      460 + */
 248  461  void
      462 +print_width(const char *v, const struct mdoc_node *child, size_t defsz)
      463 +{
      464 +        char              buf[24];
      465 +        struct roffsu     su;
      466 +        size_t            sz, chsz;
      467 +        int               numeric, remain;
      468 +
      469 +        numeric = 1;
      470 +        remain = 0;
      471 +
      472 +        /* Convert v into a number (of characters). */
      473 +        if (NULL == v)
      474 +                sz = defsz;
      475 +        else if (a2roffsu(v, &su, SCALE_MAX)) {
      476 +                if (SCALE_EN == su.unit)
      477 +                        sz = su.scale;
      478 +                else {
      479 +                        sz = 0;
      480 +                        numeric = 0;
      481 +                }
      482 +        } else
      483 +                sz = strlen(v);
      484 +
      485 +        /* XXX Rough estimation, might have multiple parts. */
      486 +        chsz = (NULL != child && MDOC_TEXT == child->type) ?
      487 +                        strlen(child->string) : 0;
      488 +
      489 +        /* Maybe we are inside an enclosing list? */
      490 +        mid_it();
      491 +
      492 +        /*
      493 +         * Save our own indentation,
      494 +         * such that child lists can use it.
      495 +         */
      496 +        Bl_stack[Bl_stack_len++] = sz + 2;
      497 +
      498 +        /* Set up the current list. */
      499 +        if (defsz && chsz > sz)
      500 +                print_block(".HP", 0);
      501 +        else {
      502 +                print_block(".TP", 0);
      503 +                remain = sz + 2;
      504 +        }
      505 +        if (numeric) {
      506 +                snprintf(buf, sizeof(buf), "%zun", sz + 2);
      507 +                print_word(buf);
      508 +        } else
      509 +                print_word(v);
      510 +        TPremain = remain;
      511 +}
      512 +
      513 +void
      514 +print_count(int *count)
      515 +{
      516 +        char              buf[12];
      517 +
      518 +        snprintf(buf, sizeof(buf), "%d.", ++*count);
      519 +        print_word(buf);
      520 +}
      521 +
      522 +void
 249  523  man_man(void *arg, const struct man *man)
 250  524  {
 251  525  
 252  526          /*
 253  527           * Dump the keep buffer.
 254  528           * We're guaranteed by now that this exists (is non-NULL).
 255  529           * Flush stdout afterward, just in case.
 256  530           */
 257  531          fputs(mparse_getkeep(man_mparse(man)), stdout);
 258  532          fflush(stdout);
 259  533  }
 260  534  
 261  535  void
 262  536  man_mdoc(void *arg, const struct mdoc *mdoc)
 263  537  {
 264      -        const struct mdoc_meta *m;
      538 +        const struct mdoc_meta *meta;
 265  539          const struct mdoc_node *n;
 266      -        struct mman             mm;
 267  540  
 268      -        m = mdoc_meta(mdoc);
      541 +        meta = mdoc_meta(mdoc);
 269  542          n = mdoc_node(mdoc);
 270  543  
 271      -        printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
 272      -                        m->title, m->msec, m->date, m->os, m->vol);
      544 +        printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n",
      545 +                        meta->title, meta->msec, meta->date,
      546 +                        meta->os, meta->vol);
 273  547  
 274      -        memset(&mm, 0, sizeof(struct mman));
      548 +        /* Disable hyphenation and if nroff, disable justification. */
      549 +        printf(".nh\n.if n .ad l");
 275  550  
 276      -        mm.need_nl = 1;
 277      -        print_node(m, n, &mm);
      551 +        outflags = MMAN_nl | MMAN_Sm;
      552 +        if (0 == fontqueue.size) {
      553 +                fontqueue.size = 8;
      554 +                fontqueue.head = fontqueue.tail = mandoc_malloc(8);
      555 +                *fontqueue.tail = 'R';
      556 +        }
      557 +        print_node(meta, n);
 278  558          putchar('\n');
 279  559  }
 280  560  
 281  561  static void
 282  562  print_node(DECL_ARGS)
 283  563  {
 284      -        const struct mdoc_node  *prev, *sub;
      564 +        const struct mdoc_node  *sub;
 285  565          const struct manact     *act;
 286  566          int                      cond, do_sub;
 287      -        
      567 +
 288  568          /*
 289  569           * Break the line if we were parsed subsequent the current node.
 290  570           * This makes the page structure be more consistent.
 291  571           */
 292      -        prev = n->prev ? n->prev : n->parent;
 293      -        if (prev && prev->line < n->line)
 294      -                mm->need_nl = 1;
      572 +        if (MMAN_spc & outflags && MDOC_LINE & n->flags)
      573 +                outflags |= MMAN_nl;
 295  574  
 296  575          act = NULL;
 297  576          cond = 0;
 298  577          do_sub = 1;
 299  578  
 300  579          if (MDOC_TEXT == n->type) {
 301  580                  /*
 302  581                   * Make sure that we don't happen to start with a
 303  582                   * control character at the start of a line.
 304  583                   */
 305      -                if (mm->need_nl && ('.' == *n->string || 
      584 +                if (MMAN_nl & outflags && ('.' == *n->string || 
 306  585                                          '\'' == *n->string)) {
 307      -                        print_word(mm, "\\&");
 308      -                        mm->need_space = 0;
      586 +                        print_word("");
      587 +                        printf("\\&");
      588 +                        outflags &= ~MMAN_spc;
 309  589                  }
 310      -                print_word(mm, n->string);
      590 +                print_word(n->string);
 311  591          } else {
 312  592                  /*
 313  593                   * Conditionally run the pre-node action handler for a
 314  594                   * node.
 315  595                   */
 316  596                  act = manacts + n->tok;
 317      -                cond = NULL == act->cond || (*act->cond)(m, n, mm);
      597 +                cond = NULL == act->cond || (*act->cond)(meta, n);
 318  598                  if (cond && act->pre)
 319      -                        do_sub = (*act->pre)(m, n, mm);
      599 +                        do_sub = (*act->pre)(meta, n);
 320  600          }
 321  601  
 322  602          /* 
 323  603           * Conditionally run all child nodes.
 324  604           * Note that this iterates over children instead of using
 325  605           * recursion.  This prevents unnecessary depth in the stack.
 326  606           */
 327  607          if (do_sub)
 328  608                  for (sub = n->child; sub; sub = sub->next)
 329      -                        print_node(m, sub, mm);
      609 +                        print_node(meta, sub);
 330  610  
 331  611          /*
 332  612           * Lastly, conditionally run the post-node handler.
 333  613           */
 334  614          if (cond && act->post)
 335      -                (*act->post)(m, n, mm);
      615 +                (*act->post)(meta, n);
 336  616  }
 337  617  
 338  618  static int
 339  619  cond_head(DECL_ARGS)
 340  620  {
 341  621  
 342  622          return(MDOC_HEAD == n->type);
 343  623  }
 344  624  
 345  625  static int
 346  626  cond_body(DECL_ARGS)
 347  627  {
 348  628  
 349  629          return(MDOC_BODY == n->type);
 350  630  }
 351  631  
 352      -/*
 353      - * Output a font encoding before a node, e.g., \fR.
 354      - * This obviously has no trailing space.
 355      - */
 356  632  static int
 357  633  pre_enc(DECL_ARGS)
 358  634  {
 359  635          const char      *prefix;
 360  636  
 361  637          prefix = manacts[n->tok].prefix;
 362  638          if (NULL == prefix)
 363  639                  return(1);
 364      -        print_word(mm, prefix);
 365      -        mm->need_space = 0;
      640 +        print_word(prefix);
      641 +        outflags &= ~MMAN_spc;
 366  642          return(1);
 367  643  }
 368  644  
 369      -/*
 370      - * Output a font encoding subsequent a node, e.g., \fP.
 371      - */
 372  645  static void
 373  646  post_enc(DECL_ARGS)
 374  647  {
 375  648          const char *suffix;
 376  649  
 377  650          suffix = manacts[n->tok].suffix;
 378  651          if (NULL == suffix)
 379  652                  return;
 380      -        mm->need_space = 0;
 381      -        print_word(mm, suffix);
      653 +        outflags &= ~MMAN_spc;
      654 +        print_word(suffix);
 382  655  }
 383  656  
 384      -/*
 385      - * Used in listings (percent = %A, e.g.).
 386      - * FIXME: this is incomplete. 
 387      - * It doesn't print a nice ", and" for lists.
 388      - */
 389  657  static void
      658 +post_font(DECL_ARGS)
      659 +{
      660 +
      661 +        font_pop();
      662 +}
      663 +
      664 +static void
 390  665  post_percent(DECL_ARGS)
 391  666  {
 392  667  
 393      -        post_enc(m, n, mm);
 394      -        if (n->next)
 395      -                print_word(mm, ",");
 396      -        else {
 397      -                print_word(mm, ".");
 398      -                mm->need_nl = 1;
      668 +        if (pre_em == manacts[n->tok].pre)
      669 +                font_pop();
      670 +        if (n->next) {
      671 +                print_word(",");
      672 +                if (n->prev &&  n->prev->tok == n->tok &&
      673 +                                n->next->tok == n->tok)
      674 +                        print_word("and");
      675 +        } else {
      676 +                print_word(".");
      677 +                outflags |= MMAN_nl;
 399  678          }
 400  679  }
 401  680  
      681 +static int
      682 +pre__t(DECL_ARGS)
      683 +{
      684 +
      685 +        if (n->parent && MDOC_Rs == n->parent->tok &&
      686 +                        n->parent->norm->Rs.quote_T) {
      687 +                print_word("");
      688 +                putchar('\"');
      689 +                outflags &= ~MMAN_spc;
      690 +        } else
      691 +                font_push('I');
      692 +        return(1);
      693 +}
      694 +
      695 +static void
      696 +post__t(DECL_ARGS)
      697 +{
      698 +
      699 +        if (n->parent && MDOC_Rs == n->parent->tok &&
      700 +                        n->parent->norm->Rs.quote_T) {
      701 +                outflags &= ~MMAN_spc;
      702 +                print_word("");
      703 +                putchar('\"');
      704 +        } else
      705 +                font_pop();
      706 +        post_percent(meta, n);
      707 +}
      708 +
 402  709  /*
 403  710   * Print before a section header.
 404  711   */
 405  712  static int
 406  713  pre_sect(DECL_ARGS)
 407  714  {
 408  715  
 409      -        if (MDOC_HEAD != n->type)
 410      -                return(1);
 411      -        mm->need_nl = 1;
 412      -        print_word(mm, manacts[n->tok].prefix);
 413      -        print_word(mm, "\"");
 414      -        mm->need_space = 0;
      716 +        if (MDOC_HEAD == n->type) {
      717 +                outflags |= MMAN_sp;
      718 +                print_block(manacts[n->tok].prefix, 0);
      719 +                print_word("");
      720 +                putchar('\"');
      721 +                outflags &= ~MMAN_spc;
      722 +        }
 415  723          return(1);
 416  724  }
 417  725  
 418  726  /*
 419  727   * Print subsequent a section header.
 420  728   */
 421  729  static void
 422  730  post_sect(DECL_ARGS)
 423  731  {
 424  732  
 425  733          if (MDOC_HEAD != n->type)
 426  734                  return;
 427      -        mm->need_space = 0;
 428      -        print_word(mm, "\"");
 429      -        mm->need_nl = 1;
      735 +        outflags &= ~MMAN_spc;
      736 +        print_word("");
      737 +        putchar('\"');
      738 +        outflags |= MMAN_nl;
      739 +        if (MDOC_Sh == n->tok && SEC_AUTHORS == n->sec)
      740 +                outflags &= ~(MMAN_An_split | MMAN_An_nosplit);
 430  741  }
 431  742  
      743 +/* See mdoc_term.c, synopsis_pre() for comments. */
      744 +static void
      745 +pre_syn(const struct mdoc_node *n)
      746 +{
      747 +
      748 +        if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags))
      749 +                return;
      750 +
      751 +        if (n->prev->tok == n->tok &&
      752 +                        MDOC_Ft != n->tok &&
      753 +                        MDOC_Fo != n->tok &&
      754 +                        MDOC_Fn != n->tok) {
      755 +                outflags |= MMAN_br;
      756 +                return;
      757 +        }
      758 +
      759 +        switch (n->prev->tok) {
      760 +        case (MDOC_Fd):
      761 +                /* FALLTHROUGH */
      762 +        case (MDOC_Fn):
      763 +                /* FALLTHROUGH */
      764 +        case (MDOC_Fo):
      765 +                /* FALLTHROUGH */
      766 +        case (MDOC_In):
      767 +                /* FALLTHROUGH */
      768 +        case (MDOC_Vt):
      769 +                outflags |= MMAN_sp;
      770 +                break;
      771 +        case (MDOC_Ft):
      772 +                if (MDOC_Fn != n->tok && MDOC_Fo != n->tok) {
      773 +                        outflags |= MMAN_sp;
      774 +                        break;
      775 +                }
      776 +                /* FALLTHROUGH */
      777 +        default:
      778 +                outflags |= MMAN_br;
      779 +                break;
      780 +        }
      781 +}
      782 +
 432  783  static int
      784 +pre_an(DECL_ARGS)
      785 +{
      786 +
      787 +        switch (n->norm->An.auth) {
      788 +        case (AUTH_split):
      789 +                outflags &= ~MMAN_An_nosplit;
      790 +                outflags |= MMAN_An_split;
      791 +                return(0);
      792 +        case (AUTH_nosplit):
      793 +                outflags &= ~MMAN_An_split;
      794 +                outflags |= MMAN_An_nosplit;
      795 +                return(0);
      796 +        default:
      797 +                if (MMAN_An_split & outflags)
      798 +                        outflags |= MMAN_br;
      799 +                else if (SEC_AUTHORS == n->sec &&
      800 +                    ! (MMAN_An_nosplit & outflags))
      801 +                        outflags |= MMAN_An_split;
      802 +                return(1);
      803 +        }
      804 +}
      805 +
      806 +static int
 433  807  pre_ap(DECL_ARGS)
 434  808  {
 435  809  
 436      -        mm->need_space = 0;
 437      -        print_word(mm, "'");
 438      -        mm->need_space = 0;
      810 +        outflags &= ~MMAN_spc;
      811 +        print_word("'");
      812 +        outflags &= ~MMAN_spc;
 439  813          return(0);
 440  814  }
 441  815  
 442  816  static int
 443  817  pre_bd(DECL_ARGS)
 444  818  {
 445  819  
      820 +        outflags &= ~(MMAN_PP | MMAN_sp | MMAN_br);
      821 +
 446  822          if (DISP_unfilled == n->norm->Bd.type ||
 447      -            DISP_literal  == n->norm->Bd.type) {
 448      -                mm->need_nl = 1;
 449      -                print_word(mm, ".nf");
 450      -        }
 451      -        mm->need_nl = 1;
      823 +            DISP_literal  == n->norm->Bd.type)
      824 +                print_line(".nf", 0);
      825 +        if (0 == n->norm->Bd.comp && NULL != n->parent->prev)
      826 +                outflags |= MMAN_sp;
      827 +        print_offs(n->norm->Bd.offs);
 452  828          return(1);
 453  829  }
 454  830  
 455  831  static void
 456  832  post_bd(DECL_ARGS)
 457  833  {
 458  834  
      835 +        /* Close out this display. */
      836 +        print_line(".RE", MMAN_nl);
 459  837          if (DISP_unfilled == n->norm->Bd.type ||
 460      -            DISP_literal  == n->norm->Bd.type) {
 461      -                mm->need_nl = 1;
 462      -                print_word(mm, ".fi");
      838 +            DISP_literal  == n->norm->Bd.type)
      839 +                print_line(".fi", MMAN_nl);
      840 +
      841 +        /* Maybe we are inside an enclosing list? */
      842 +        if (NULL != n->parent->next)
      843 +                mid_it();
      844 +}
      845 +
      846 +static int
      847 +pre_bf(DECL_ARGS)
      848 +{
      849 +
      850 +        switch (n->type) {
      851 +        case (MDOC_BLOCK):
      852 +                return(1);
      853 +        case (MDOC_BODY):
      854 +                break;
      855 +        default:
      856 +                return(0);
 463  857          }
 464      -        mm->need_nl = 1;
      858 +        switch (n->norm->Bf.font) {
      859 +        case (FONT_Em):
      860 +                font_push('I');
      861 +                break;
      862 +        case (FONT_Sy):
      863 +                font_push('B');
      864 +                break;
      865 +        default:
      866 +                font_push('R');
      867 +                break;
      868 +        }
      869 +        return(1);
 465  870  }
 466  871  
      872 +static void
      873 +post_bf(DECL_ARGS)
      874 +{
      875 +
      876 +        if (MDOC_BODY == n->type)
      877 +                font_pop();
      878 +}
      879 +
 467  880  static int
      881 +pre_bk(DECL_ARGS)
      882 +{
      883 +
      884 +        switch (n->type) {
      885 +        case (MDOC_BLOCK):
      886 +                return(1);
      887 +        case (MDOC_BODY):
      888 +                outflags |= MMAN_Bk;
      889 +                return(1);
      890 +        default:
      891 +                return(0);
      892 +        }
      893 +}
      894 +
      895 +static void
      896 +post_bk(DECL_ARGS)
      897 +{
      898 +
      899 +        if (MDOC_BODY == n->type)
      900 +                outflags &= ~MMAN_Bk;
      901 +}
      902 +
      903 +static int
      904 +pre_bl(DECL_ARGS)
      905 +{
      906 +        size_t           icol;
      907 +
      908 +        /*
      909 +         * print_offs() will increase the -offset to account for
      910 +         * a possible enclosing .It, but any enclosed .It blocks
      911 +         * just nest and do not add up their indentation.
      912 +         */
      913 +        if (n->norm->Bl.offs) {
      914 +                print_offs(n->norm->Bl.offs);
      915 +                Bl_stack[Bl_stack_len++] = 0;
      916 +        }
      917 +
      918 +        switch (n->norm->Bl.type) {
      919 +        case (LIST_enum):
      920 +                n->norm->Bl.count = 0;
      921 +                return(1);
      922 +        case (LIST_column):
      923 +                break;
      924 +        default:
      925 +                return(1);
      926 +        }
      927 +
      928 +        print_line(".TS", MMAN_nl);
      929 +        for (icol = 0; icol < n->norm->Bl.ncols; icol++)
      930 +                print_word("l");
      931 +        print_word(".");
      932 +        outflags |= MMAN_nl;
      933 +        return(1);
      934 +}
      935 +
      936 +static void
      937 +post_bl(DECL_ARGS)
      938 +{
      939 +
      940 +        switch (n->norm->Bl.type) {
      941 +        case (LIST_column):
      942 +                print_line(".TE", 0);
      943 +                break;
      944 +        case (LIST_enum):
      945 +                n->norm->Bl.count = 0;
      946 +                break;
      947 +        default:
      948 +                break;
      949 +        }
      950 +
      951 +        if (n->norm->Bl.offs) {
      952 +                print_line(".RE", MMAN_nl);
      953 +                assert(Bl_stack_len);
      954 +                Bl_stack_len--;
      955 +                assert(0 == Bl_stack[Bl_stack_len]);
      956 +        } else {
      957 +                outflags |= MMAN_PP | MMAN_nl;
      958 +                outflags &= ~(MMAN_sp | MMAN_br);
      959 +        }
      960 +
      961 +        /* Maybe we are inside an enclosing list? */
      962 +        if (NULL != n->parent->next)
      963 +                mid_it();
      964 +
      965 +}
      966 +
      967 +static int
 468  968  pre_br(DECL_ARGS)
 469  969  {
 470  970  
 471      -        mm->need_nl = 1;
 472      -        print_word(mm, ".br");
 473      -        mm->need_nl = 1;
      971 +        outflags |= MMAN_br;
 474  972          return(0);
 475  973  }
 476  974  
 477  975  static int
 478  976  pre_bx(DECL_ARGS)
 479  977  {
 480  978  
 481  979          n = n->child;
 482  980          if (n) {
 483      -                print_word(mm, n->string);
 484      -                mm->need_space = 0;
      981 +                print_word(n->string);
      982 +                outflags &= ~MMAN_spc;
 485  983                  n = n->next;
 486  984          }
 487      -        print_word(mm, "BSD");
      985 +        print_word("BSD");
 488  986          if (NULL == n)
 489  987                  return(0);
 490      -        mm->need_space = 0;
 491      -        print_word(mm, "-");
 492      -        mm->need_space = 0;
 493      -        print_word(mm, n->string);
      988 +        outflags &= ~MMAN_spc;
      989 +        print_word("-");
      990 +        outflags &= ~MMAN_spc;
      991 +        print_word(n->string);
 494  992          return(0);
 495  993  }
 496  994  
 497  995  static int
 498  996  pre_dl(DECL_ARGS)
 499  997  {
 500  998  
 501      -        mm->need_nl = 1;
 502      -        print_word(mm, ".RS 6n");
 503      -        mm->need_nl = 1;
      999 +        print_offs("6n");
 504 1000          return(1);
 505 1001  }
 506 1002  
 507 1003  static void
 508 1004  post_dl(DECL_ARGS)
 509 1005  {
 510 1006  
 511      -        mm->need_nl = 1;
 512      -        print_word(mm, ".RE");
 513      -        mm->need_nl = 1;
     1007 +        print_line(".RE", MMAN_nl);
     1008 +
     1009 +        /* Maybe we are inside an enclosing list? */
     1010 +        if (NULL != n->parent->next)
     1011 +                mid_it();
 514 1012  }
 515 1013  
 516 1014  static int
     1015 +pre_em(DECL_ARGS)
     1016 +{
     1017 +
     1018 +        font_push('I');
     1019 +        return(1);
     1020 +}
     1021 +
     1022 +static void
     1023 +post_eo(DECL_ARGS)
     1024 +{
     1025 +
     1026 +        if (MDOC_HEAD == n->type || MDOC_BODY == n->type)
     1027 +                outflags &= ~MMAN_spc;
     1028 +}
     1029 +
     1030 +static int
     1031 +pre_fa(DECL_ARGS)
     1032 +{
     1033 +        int      am_Fa;
     1034 +
     1035 +        am_Fa = MDOC_Fa == n->tok;
     1036 +
     1037 +        if (am_Fa)
     1038 +                n = n->child;
     1039 +
     1040 +        while (NULL != n) {
     1041 +                font_push('I');
     1042 +                if (am_Fa || MDOC_SYNPRETTY & n->flags)
     1043 +                        outflags |= MMAN_nbrword;
     1044 +                print_node(meta, n);
     1045 +                font_pop();
     1046 +                if (NULL != (n = n->next))
     1047 +                        print_word(",");
     1048 +        }
     1049 +        return(0);
     1050 +}
     1051 +
     1052 +static void
     1053 +post_fa(DECL_ARGS)
     1054 +{
     1055 +
     1056 +        if (NULL != n->next && MDOC_Fa == n->next->tok)
     1057 +                print_word(",");
     1058 +}
     1059 +
     1060 +static int
     1061 +pre_fd(DECL_ARGS)
     1062 +{
     1063 +
     1064 +        pre_syn(n);
     1065 +        font_push('B');
     1066 +        return(1);
     1067 +}
     1068 +
     1069 +static void
     1070 +post_fd(DECL_ARGS)
     1071 +{
     1072 +
     1073 +        font_pop();
     1074 +        outflags |= MMAN_br;
     1075 +}
     1076 +
     1077 +static int
     1078 +pre_fl(DECL_ARGS)
     1079 +{
     1080 +
     1081 +        font_push('B');
     1082 +        print_word("\\-");
     1083 +        outflags &= ~MMAN_spc;
     1084 +        return(1);
     1085 +}
     1086 +
     1087 +static void
     1088 +post_fl(DECL_ARGS)
     1089 +{
     1090 +
     1091 +        font_pop();
     1092 +        if (0 == n->nchild && NULL != n->next &&
     1093 +                        n->next->line == n->line)
     1094 +                outflags &= ~MMAN_spc;
     1095 +}
     1096 +
     1097 +static int
     1098 +pre_fn(DECL_ARGS)
     1099 +{
     1100 +
     1101 +        pre_syn(n);
     1102 +
     1103 +        n = n->child;
     1104 +        if (NULL == n)
     1105 +                return(0);
     1106 +
     1107 +        if (MDOC_SYNPRETTY & n->flags)
     1108 +                print_block(".HP 4n", MMAN_nl);
     1109 +
     1110 +        font_push('B');
     1111 +        print_node(meta, n);
     1112 +        font_pop();
     1113 +        outflags &= ~MMAN_spc;
     1114 +        print_word("(");
     1115 +        outflags &= ~MMAN_spc;
     1116 +
     1117 +        n = n->next;
     1118 +        if (NULL != n)
     1119 +                pre_fa(meta, n);
     1120 +        return(0);
     1121 +}
     1122 +
     1123 +static void
     1124 +post_fn(DECL_ARGS)
     1125 +{
     1126 +
     1127 +        print_word(")");
     1128 +        if (MDOC_SYNPRETTY & n->flags) {
     1129 +                print_word(";");
     1130 +                outflags |= MMAN_PP;
     1131 +        }
     1132 +}
     1133 +
     1134 +static int
     1135 +pre_fo(DECL_ARGS)
     1136 +{
     1137 +
     1138 +        switch (n->type) {
     1139 +        case (MDOC_BLOCK):
     1140 +                pre_syn(n);
     1141 +                break;
     1142 +        case (MDOC_HEAD):
     1143 +                if (MDOC_SYNPRETTY & n->flags)
     1144 +                        print_block(".HP 4n", MMAN_nl);
     1145 +                font_push('B');
     1146 +                break;
     1147 +        case (MDOC_BODY):
     1148 +                outflags &= ~MMAN_spc;
     1149 +                print_word("(");
     1150 +                outflags &= ~MMAN_spc;
     1151 +                break;
     1152 +        default:
     1153 +                break;
     1154 +        }
     1155 +        return(1);
     1156 +}
     1157 +
     1158 +static void
     1159 +post_fo(DECL_ARGS)
     1160 +{
     1161 +
     1162 +        switch (n->type) {
     1163 +        case (MDOC_HEAD):
     1164 +                font_pop();
     1165 +                break;
     1166 +        case (MDOC_BODY):
     1167 +                post_fn(meta, n);
     1168 +                break;
     1169 +        default:
     1170 +                break;
     1171 +        }
     1172 +}
     1173 +
     1174 +static int
     1175 +pre_ft(DECL_ARGS)
     1176 +{
     1177 +
     1178 +        pre_syn(n);
     1179 +        font_push('I');
     1180 +        return(1);
     1181 +}
     1182 +
     1183 +static int
     1184 +pre_in(DECL_ARGS)
     1185 +{
     1186 +
     1187 +        if (MDOC_SYNPRETTY & n->flags) {
     1188 +                pre_syn(n);
     1189 +                font_push('B');
     1190 +                print_word("#include <");
     1191 +                outflags &= ~MMAN_spc;
     1192 +        } else {
     1193 +                print_word("<");
     1194 +                outflags &= ~MMAN_spc;
     1195 +                font_push('I');
     1196 +        }
     1197 +        return(1);
     1198 +}
     1199 +
     1200 +static void
     1201 +post_in(DECL_ARGS)
     1202 +{
     1203 +
     1204 +        if (MDOC_SYNPRETTY & n->flags) {
     1205 +                outflags &= ~MMAN_spc;
     1206 +                print_word(">");
     1207 +                font_pop();
     1208 +                outflags |= MMAN_br;
     1209 +        } else {
     1210 +                font_pop();
     1211 +                outflags &= ~MMAN_spc;
     1212 +                print_word(">");
     1213 +        }
     1214 +}
     1215 +
     1216 +static int
 517 1217  pre_it(DECL_ARGS)
 518 1218  {
 519 1219          const struct mdoc_node *bln;
 520 1220  
 521      -        if (MDOC_HEAD == n->type) {
 522      -                mm->need_nl = 1;
 523      -                print_word(mm, ".TP");
 524      -                bln = n->parent->parent->prev;
     1221 +        switch (n->type) {
     1222 +        case (MDOC_HEAD):
     1223 +                outflags |= MMAN_PP | MMAN_nl;
     1224 +                bln = n->parent->parent;
     1225 +                if (0 == bln->norm->Bl.comp ||
     1226 +                    (NULL == n->parent->prev &&
     1227 +                     NULL == bln->parent->prev))
     1228 +                        outflags |= MMAN_sp;
     1229 +                outflags &= ~MMAN_br;
 525 1230                  switch (bln->norm->Bl.type) {
     1231 +                case (LIST_item):
     1232 +                        return(0);
     1233 +                case (LIST_inset):
     1234 +                        /* FALLTHROUGH */
     1235 +                case (LIST_diag):
     1236 +                        /* FALLTHROUGH */
     1237 +                case (LIST_ohang):
     1238 +                        if (bln->norm->Bl.type == LIST_diag)
     1239 +                                print_line(".B \"", 0);
     1240 +                        else
     1241 +                                print_line(".R \"", 0);
     1242 +                        outflags &= ~MMAN_spc;
     1243 +                        return(1);
 526 1244                  case (LIST_bullet):
 527      -                        print_word(mm, "4n");
 528      -                        mm->need_nl = 1;
 529      -                        print_word(mm, "\\fBo\\fP");
     1245 +                        /* FALLTHROUGH */
     1246 +                case (LIST_dash):
     1247 +                        /* FALLTHROUGH */
     1248 +                case (LIST_hyphen):
     1249 +                        print_width(bln->norm->Bl.width, NULL, 0);
     1250 +                        TPremain = 0;
     1251 +                        outflags |= MMAN_nl;
     1252 +                        font_push('B');
     1253 +                        if (LIST_bullet == bln->norm->Bl.type)
     1254 +                                print_word("o");
     1255 +                        else
     1256 +                                print_word("-");
     1257 +                        font_pop();
 530 1258                          break;
     1259 +                case (LIST_enum):
     1260 +                        print_width(bln->norm->Bl.width, NULL, 0);
     1261 +                        TPremain = 0;
     1262 +                        outflags |= MMAN_nl;
     1263 +                        print_count(&bln->norm->Bl.count);
     1264 +                        break;
     1265 +                case (LIST_hang):
     1266 +                        print_width(bln->norm->Bl.width, n->child, 6);
     1267 +                        TPremain = 0;
     1268 +                        break;
     1269 +                case (LIST_tag):
     1270 +                        print_width(bln->norm->Bl.width, n->child, 0);
     1271 +                        putchar('\n');
     1272 +                        outflags &= ~MMAN_spc;
     1273 +                        return(1);
 531 1274                  default:
 532      -                        if (bln->norm->Bl.width)
 533      -                                print_word(mm, bln->norm->Bl.width);
     1275 +                        return(1);
     1276 +                }
     1277 +                outflags |= MMAN_nl;
     1278 +        default:
     1279 +                break;
     1280 +        }
     1281 +        return(1);
     1282 +}
     1283 +
     1284 +/*
     1285 + * This function is called after closing out an indented block.
     1286 + * If we are inside an enclosing list, restore its indentation.
     1287 + */
     1288 +static void
     1289 +mid_it(void)
     1290 +{
     1291 +        char             buf[24];
     1292 +
     1293 +        /* Nothing to do outside a list. */
     1294 +        if (0 == Bl_stack_len || 0 == Bl_stack[Bl_stack_len - 1])
     1295 +                return;
     1296 +
     1297 +        /* The indentation has already been set up. */
     1298 +        if (Bl_stack_post[Bl_stack_len - 1])
     1299 +                return;
     1300 +
     1301 +        /* Restore the indentation of the enclosing list. */
     1302 +        print_line(".RS", MMAN_Bk_susp);
     1303 +        snprintf(buf, sizeof(buf), "%zun", Bl_stack[Bl_stack_len - 1]);
     1304 +        print_word(buf);
     1305 +
     1306 +        /* Remeber to close out this .RS block later. */
     1307 +        Bl_stack_post[Bl_stack_len - 1] = 1;
     1308 +}
     1309 +
     1310 +static void
     1311 +post_it(DECL_ARGS)
     1312 +{
     1313 +        const struct mdoc_node *bln;
     1314 +
     1315 +        bln = n->parent->parent;
     1316 +
     1317 +        switch (n->type) {
     1318 +        case (MDOC_HEAD):
     1319 +                switch (bln->norm->Bl.type) {
     1320 +                case (LIST_diag):
     1321 +                        outflags &= ~MMAN_spc;
     1322 +                        print_word("\\ ");
 534 1323                          break;
     1324 +                case (LIST_ohang):
     1325 +                        outflags |= MMAN_br;
     1326 +                        break;
     1327 +                default:
     1328 +                        break;
 535 1329                  }
 536      -                mm->need_nl = 1;
     1330 +                break;
     1331 +        case (MDOC_BODY):
     1332 +                switch (bln->norm->Bl.type) {
     1333 +                case (LIST_bullet):
     1334 +                        /* FALLTHROUGH */
     1335 +                case (LIST_dash):
     1336 +                        /* FALLTHROUGH */
     1337 +                case (LIST_hyphen):
     1338 +                        /* FALLTHROUGH */
     1339 +                case (LIST_enum):
     1340 +                        /* FALLTHROUGH */
     1341 +                case (LIST_hang):
     1342 +                        /* FALLTHROUGH */
     1343 +                case (LIST_tag):
     1344 +                        assert(Bl_stack_len);
     1345 +                        Bl_stack[--Bl_stack_len] = 0;
     1346 +
     1347 +                        /*
     1348 +                         * Our indentation had to be restored
     1349 +                         * after a child display or child list.
     1350 +                         * Close out that indentation block now.
     1351 +                         */
     1352 +                        if (Bl_stack_post[Bl_stack_len]) {
     1353 +                                print_line(".RE", MMAN_nl);
     1354 +                                Bl_stack_post[Bl_stack_len] = 0;
     1355 +                        }
     1356 +                        break;
     1357 +                case (LIST_column):
     1358 +                        if (NULL != n->next) {
     1359 +                                putchar('\t');
     1360 +                                outflags &= ~MMAN_spc;
     1361 +                        }
     1362 +                        break;
     1363 +                default:
     1364 +                        break;
     1365 +                }
     1366 +                break;
     1367 +        default:
     1368 +                break;
 537 1369          }
     1370 +}
     1371 +
     1372 +static void
     1373 +post_lb(DECL_ARGS)
     1374 +{
     1375 +
     1376 +        if (SEC_LIBRARY == n->sec)
     1377 +                outflags |= MMAN_br;
     1378 +}
     1379 +
     1380 +static int
     1381 +pre_lk(DECL_ARGS)
     1382 +{
     1383 +        const struct mdoc_node *link, *descr;
     1384 +
     1385 +        if (NULL == (link = n->child))
     1386 +                return(0);
     1387 +
     1388 +        if (NULL != (descr = link->next)) {
     1389 +                font_push('I');
     1390 +                while (NULL != descr) {
     1391 +                        print_word(descr->string);
     1392 +                        descr = descr->next;
     1393 +                }
     1394 +                print_word(":");
     1395 +                font_pop();
     1396 +        }
     1397 +
     1398 +        font_push('B');
     1399 +        print_word(link->string);
     1400 +        font_pop();
     1401 +        return(0);
     1402 +}
     1403 +
     1404 +static int
     1405 +pre_li(DECL_ARGS)
     1406 +{
     1407 +
     1408 +        font_push('R');
 538 1409          return(1);
 539 1410  }
 540 1411  
 541 1412  static int
 542 1413  pre_nm(DECL_ARGS)
 543 1414  {
     1415 +        char    *name;
 544 1416  
     1417 +        if (MDOC_BLOCK == n->type) {
     1418 +                outflags |= MMAN_Bk;
     1419 +                pre_syn(n);
     1420 +        }
 545 1421          if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
 546 1422                  return(1);
 547      -        print_word(mm, "\\fB");
 548      -        mm->need_space = 0;
     1423 +        name = n->child ? n->child->string : meta->name;
     1424 +        if (NULL == name)
     1425 +                return(0);
     1426 +        if (MDOC_HEAD == n->type) {
     1427 +                if (NULL == n->parent->prev)
     1428 +                        outflags |= MMAN_sp;
     1429 +                print_block(".HP", 0);
     1430 +                printf(" %zun", strlen(name) + 1);
     1431 +                outflags |= MMAN_nl;
     1432 +        }
     1433 +        font_push('B');
 549 1434          if (NULL == n->child)
 550      -                print_word(mm, m->name);
     1435 +                print_word(meta->name);
 551 1436          return(1);
 552 1437  }
 553 1438  
 554 1439  static void
 555 1440  post_nm(DECL_ARGS)
 556 1441  {
 557 1442  
 558      -        if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
 559      -                return;
 560      -        mm->need_space = 0;
 561      -        print_word(mm, "\\fP");
     1443 +        switch (n->type) {
     1444 +        case (MDOC_BLOCK):
     1445 +                outflags &= ~MMAN_Bk;
     1446 +                break;
     1447 +        case (MDOC_HEAD):
     1448 +                /* FALLTHROUGH */
     1449 +        case (MDOC_ELEM):
     1450 +                font_pop();
     1451 +                break;
     1452 +        default:
     1453 +                break;
     1454 +        }
 562 1455  }
 563 1456  
 564 1457  static int
     1458 +pre_no(DECL_ARGS)
     1459 +{
     1460 +
     1461 +        outflags |= MMAN_spc_force;
     1462 +        return(1);
     1463 +}
     1464 +
     1465 +static int
 565 1466  pre_ns(DECL_ARGS)
 566 1467  {
 567 1468  
 568      -        mm->need_space = 0;
     1469 +        outflags &= ~MMAN_spc;
 569 1470          return(0);
 570 1471  }
 571 1472  
 572 1473  static void
 573 1474  post_pf(DECL_ARGS)
 574 1475  {
 575 1476  
 576      -        mm->need_space = 0;
     1477 +        outflags &= ~MMAN_spc;
 577 1478  }
 578 1479  
 579 1480  static int
 580 1481  pre_pp(DECL_ARGS)
 581 1482  {
 582 1483  
 583      -        mm->need_nl = 1;
 584      -        if (MDOC_It == n->parent->tok)
 585      -                print_word(mm, ".sp");
 586      -        else
 587      -                print_word(mm, ".PP");
 588      -        mm->need_nl = 1;
     1484 +        if (MDOC_It != n->parent->tok)
     1485 +                outflags |= MMAN_PP;
     1486 +        outflags |= MMAN_sp | MMAN_nl;
     1487 +        outflags &= ~MMAN_br;
     1488 +        return(0);
     1489 +}
     1490 +
     1491 +static int
     1492 +pre_rs(DECL_ARGS)
     1493 +{
     1494 +
     1495 +        if (SEC_SEE_ALSO == n->sec) {
     1496 +                outflags |= MMAN_PP | MMAN_sp | MMAN_nl;
     1497 +                outflags &= ~MMAN_br;
     1498 +        }
 589 1499          return(1);
 590 1500  }
 591 1501  
 592 1502  static int
     1503 +pre_sm(DECL_ARGS)
     1504 +{
     1505 +
     1506 +        assert(n->child && MDOC_TEXT == n->child->type);
     1507 +        if (0 == strcmp("on", n->child->string))
     1508 +                outflags |= MMAN_Sm | MMAN_spc;
     1509 +        else
     1510 +                outflags &= ~MMAN_Sm;
     1511 +        return(0);
     1512 +}
     1513 +
     1514 +static int
 593 1515  pre_sp(DECL_ARGS)
 594 1516  {
 595 1517  
 596      -        mm->need_nl = 1;
 597      -        print_word(mm, ".sp");
     1518 +        if (MMAN_PP & outflags) {
     1519 +                outflags &= ~MMAN_PP;
     1520 +                print_line(".PP", 0);
     1521 +        } else
     1522 +                print_line(".sp", 0);
 598 1523          return(1);
 599 1524  }
 600 1525  
 601 1526  static void
 602 1527  post_sp(DECL_ARGS)
 603 1528  {
 604 1529  
 605      -        mm->need_nl = 1;
     1530 +        outflags |= MMAN_nl;
 606 1531  }
 607 1532  
 608 1533  static int
     1534 +pre_sy(DECL_ARGS)
     1535 +{
     1536 +
     1537 +        font_push('B');
     1538 +        return(1);
     1539 +}
     1540 +
     1541 +static int
     1542 +pre_vt(DECL_ARGS)
     1543 +{
     1544 +
     1545 +        if (MDOC_SYNPRETTY & n->flags) {
     1546 +                switch (n->type) {
     1547 +                case (MDOC_BLOCK):
     1548 +                        pre_syn(n);
     1549 +                        return(1);
     1550 +                case (MDOC_BODY):
     1551 +                        break;
     1552 +                default:
     1553 +                        return(0);
     1554 +                }
     1555 +        }
     1556 +        font_push('I');
     1557 +        return(1);
     1558 +}
     1559 +
     1560 +static void
     1561 +post_vt(DECL_ARGS)
     1562 +{
     1563 +
     1564 +        if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type)
     1565 +                return;
     1566 +        font_pop();
     1567 +}
     1568 +
     1569 +static int
 609 1570  pre_xr(DECL_ARGS)
 610 1571  {
 611 1572  
 612 1573          n = n->child;
 613 1574          if (NULL == n)
 614 1575                  return(0);
 615      -        print_node(m, n, mm);
     1576 +        print_node(meta, n);
 616 1577          n = n->next;
 617 1578          if (NULL == n)
 618 1579                  return(0);
 619      -        mm->need_space = 0;
 620      -        print_word(mm, "(");
 621      -        print_node(m, n, mm);
 622      -        print_word(mm, ")");
     1580 +        outflags &= ~MMAN_spc;
     1581 +        print_word("(");
     1582 +        print_node(meta, n);
     1583 +        print_word(")");
 623 1584          return(0);
 624 1585  }
 625 1586  
 626 1587  static int
 627 1588  pre_ux(DECL_ARGS)
 628 1589  {
 629 1590  
 630      -        print_word(mm, manacts[n->tok].prefix);
     1591 +        print_word(manacts[n->tok].prefix);
 631 1592          if (NULL == n->child)
 632 1593                  return(0);
 633      -        mm->need_space = 0;
 634      -        print_word(mm, "\\~");
 635      -        mm->need_space = 0;
     1594 +        outflags &= ~MMAN_spc;
     1595 +        print_word("\\ ");
     1596 +        outflags &= ~MMAN_spc;
 636 1597          return(1);
 637 1598  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX