Print this page
5051 import mdocml-1.12.3
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Approved by: TBD

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mandoc/man_term.c
          +++ new/usr/src/cmd/mandoc/man_term.c
   1      -/*      $Id: man_term.c,v 1.127 2012/01/03 15:16:24 kristaps Exp $ */
        1 +/*      $Id: man_term.c,v 1.139 2013/12/22 23:34:13 schwarze Exp $ */
   2    2  /*
   3      - * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
   4      - * Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
        3 + * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
        4 + * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
   5    5   *
   6    6   * Permission to use, copy, modify, and distribute this software for any
   7    7   * purpose with or without fee is hereby granted, provided that the above
   8    8   * copyright notice and this permission notice appear in all copies.
   9    9   *
  10   10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11   11   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12   12   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13   13   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14   14   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
↓ open down ↓ 13 lines elided ↑ open up ↑
  28   28  #include <string.h>
  29   29  
  30   30  #include "mandoc.h"
  31   31  #include "out.h"
  32   32  #include "man.h"
  33   33  #include "term.h"
  34   34  #include "main.h"
  35   35  
  36   36  #define MAXMARGINS        64 /* maximum number of indented scopes */
  37   37  
  38      -/* FIXME: have PD set the default vspace width. */
  39      -
  40   38  struct  mtermp {
  41   39          int               fl;
  42   40  #define MANT_LITERAL     (1 << 0)
  43   41          size_t            lmargin[MAXMARGINS]; /* margins (incl. visible page) */
  44   42          int               lmargincur; /* index of current margin */
  45   43          int               lmarginsz; /* actual number of nested margins */
  46   44          size_t            offset; /* default offset to visible page */
       45 +        int               pardist; /* vert. space before par., unit: [v] */
  47   46  };
  48   47  
  49   48  #define DECL_ARGS         struct termp *p, \
  50   49                            struct mtermp *mt, \
  51   50                            const struct man_node *n, \
  52      -                          const struct man_meta *m
       51 +                          const struct man_meta *meta
  53   52  
  54   53  struct  termact {
  55   54          int             (*pre)(DECL_ARGS);
  56   55          void            (*post)(DECL_ARGS);
  57   56          int               flags;
  58   57  #define MAN_NOTEXT       (1 << 0) /* Never has text children. */
  59   58  };
  60   59  
  61   60  static  int               a2width(const struct termp *, const char *);
  62   61  static  size_t            a2height(const struct termp *, const char *);
  63   62  
  64   63  static  void              print_man_nodelist(DECL_ARGS);
  65   64  static  void              print_man_node(DECL_ARGS);
  66   65  static  void              print_man_head(struct termp *, const void *);
  67   66  static  void              print_man_foot(struct termp *, const void *);
  68   67  static  void              print_bvspace(struct termp *, 
  69      -                                const struct man_node *);
       68 +                                const struct man_node *, int);
  70   69  
  71   70  static  int               pre_B(DECL_ARGS);
  72   71  static  int               pre_HP(DECL_ARGS);
  73   72  static  int               pre_I(DECL_ARGS);
  74   73  static  int               pre_IP(DECL_ARGS);
  75   74  static  int               pre_OP(DECL_ARGS);
       75 +static  int               pre_PD(DECL_ARGS);
  76   76  static  int               pre_PP(DECL_ARGS);
  77   77  static  int               pre_RS(DECL_ARGS);
  78   78  static  int               pre_SH(DECL_ARGS);
  79   79  static  int               pre_SS(DECL_ARGS);
  80   80  static  int               pre_TP(DECL_ARGS);
       81 +static  int               pre_UR(DECL_ARGS);
  81   82  static  int               pre_alternate(DECL_ARGS);
  82   83  static  int               pre_ft(DECL_ARGS);
  83   84  static  int               pre_ign(DECL_ARGS);
  84   85  static  int               pre_in(DECL_ARGS);
  85   86  static  int               pre_literal(DECL_ARGS);
  86   87  static  int               pre_sp(DECL_ARGS);
  87   88  
  88   89  static  void              post_IP(DECL_ARGS);
  89   90  static  void              post_HP(DECL_ARGS);
  90   91  static  void              post_RS(DECL_ARGS);
  91   92  static  void              post_SH(DECL_ARGS);
  92   93  static  void              post_SS(DECL_ARGS);
  93   94  static  void              post_TP(DECL_ARGS);
       95 +static  void              post_UR(DECL_ARGS);
  94   96  
  95   97  static  const struct termact termacts[MAN_MAX] = {
  96   98          { pre_sp, NULL, MAN_NOTEXT }, /* br */
  97   99          { NULL, NULL, 0 }, /* TH */
  98  100          { pre_SH, post_SH, 0 }, /* SH */
  99  101          { pre_SS, post_SS, 0 }, /* SS */
 100  102          { pre_TP, post_TP, 0 }, /* TP */
 101  103          { pre_PP, NULL, 0 }, /* LP */
 102  104          { pre_PP, NULL, 0 }, /* PP */
 103  105          { pre_PP, NULL, 0 }, /* P */
↓ open down ↓ 11 lines elided ↑ open up ↑
 115  117          { pre_alternate, NULL, 0 }, /* IR */
 116  118          { pre_alternate, NULL, 0 }, /* RI */
 117  119          { pre_ign, NULL, MAN_NOTEXT }, /* na */
 118  120          { pre_sp, NULL, MAN_NOTEXT }, /* sp */
 119  121          { pre_literal, NULL, 0 }, /* nf */
 120  122          { pre_literal, NULL, 0 }, /* fi */
 121  123          { NULL, NULL, 0 }, /* RE */
 122  124          { pre_RS, post_RS, 0 }, /* RS */
 123  125          { pre_ign, NULL, 0 }, /* DT */
 124  126          { pre_ign, NULL, 0 }, /* UC */
 125      -        { pre_ign, NULL, 0 }, /* PD */
      127 +        { pre_PD, NULL, MAN_NOTEXT }, /* PD */
 126  128          { pre_ign, NULL, 0 }, /* AT */
 127  129          { pre_in, NULL, MAN_NOTEXT }, /* in */
 128  130          { pre_ft, NULL, MAN_NOTEXT }, /* ft */
 129  131          { pre_OP, NULL, 0 }, /* OP */
      132 +        { pre_literal, NULL, 0 }, /* EX */
      133 +        { pre_literal, NULL, 0 }, /* EE */
      134 +        { pre_UR, post_UR, 0 }, /* UR */
      135 +        { NULL, NULL, 0 }, /* UE */
 130  136  };
 131  137  
 132  138  
 133  139  
 134  140  void
 135  141  terminal_man(void *arg, const struct man *man)
 136  142  {
 137  143          struct termp            *p;
 138  144          const struct man_node   *n;
 139      -        const struct man_meta   *m;
      145 +        const struct man_meta   *meta;
 140  146          struct mtermp            mt;
 141  147  
 142  148          p = (struct termp *)arg;
 143  149  
 144  150          if (0 == p->defindent)
 145  151                  p->defindent = 7;
 146  152  
 147  153          p->overstep = 0;
 148  154          p->maxrmargin = p->defrmargin;
 149  155          p->tabwidth = term_len(p, 5);
 150  156  
 151  157          if (NULL == p->symtab)
 152  158                  p->symtab = mchars_alloc();
 153  159  
 154  160          n = man_node(man);
 155      -        m = man_meta(man);
      161 +        meta = man_meta(man);
 156  162  
 157      -        term_begin(p, print_man_head, print_man_foot, m);
      163 +        term_begin(p, print_man_head, print_man_foot, meta);
 158  164          p->flags |= TERMP_NOSPACE;
 159  165  
 160  166          memset(&mt, 0, sizeof(struct mtermp));
 161  167  
 162  168          mt.lmargin[mt.lmargincur] = term_len(p, p->defindent);
 163  169          mt.offset = term_len(p, p->defindent);
      170 +        mt.pardist = 1;
 164  171  
 165  172          if (n->child)
 166      -                print_man_nodelist(p, &mt, n->child, m);
      173 +                print_man_nodelist(p, &mt, n->child, meta);
 167  174  
 168  175          term_end(p);
 169  176  }
 170  177  
 171  178  
 172  179  static size_t
 173  180  a2height(const struct termp *p, const char *cp)
 174  181  {
 175  182          struct roffsu    su;
 176  183  
↓ open down ↓ 17 lines elided ↑ open up ↑
 194  201  
 195  202  /*
 196  203   * Printing leading vertical space before a block.
 197  204   * This is used for the paragraph macros.
 198  205   * The rules are pretty simple, since there's very little nesting going
 199  206   * on here.  Basically, if we're the first within another block (SS/SH),
 200  207   * then don't emit vertical space.  If we are (RS), then do.  If not the
 201  208   * first, print it.
 202  209   */
 203  210  static void
 204      -print_bvspace(struct termp *p, const struct man_node *n)
      211 +print_bvspace(struct termp *p, const struct man_node *n, int pardist)
 205  212  {
      213 +        int      i;
 206  214  
 207  215          term_newln(p);
 208  216  
 209  217          if (n->body && n->body->child)
 210  218                  if (MAN_TBL == n->body->child->type)
 211  219                          return;
 212  220  
 213  221          if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok)
 214  222                  if (NULL == n->prev)
 215  223                          return;
 216  224  
 217      -        term_vspace(p);
      225 +        for (i = 0; i < pardist; i++)
      226 +                term_vspace(p);
 218  227  }
 219  228  
 220  229  /* ARGSUSED */
 221  230  static int
 222  231  pre_ign(DECL_ARGS)
 223  232  {
 224  233  
 225  234          return(0);
 226  235  }
 227  236  
↓ open down ↓ 8 lines elided ↑ open up ↑
 236  245  }
 237  246  
 238  247  
 239  248  /* ARGSUSED */
 240  249  static int
 241  250  pre_literal(DECL_ARGS)
 242  251  {
 243  252  
 244  253          term_newln(p);
 245  254  
 246      -        if (MAN_nf == n->tok)
      255 +        if (MAN_nf == n->tok || MAN_EX == n->tok)
 247  256                  mt->fl |= MANT_LITERAL;
 248  257          else
 249  258                  mt->fl &= ~MANT_LITERAL;
 250  259  
 251  260          /*
 252  261           * Unlike .IP and .TP, .HP does not have a HEAD.
 253  262           * So in case a second call to term_flushln() is needed,
 254  263           * indentation has to be set up explicitly.
 255  264           */
 256  265          if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) {
 257  266                  p->offset = p->rmargin;
 258  267                  p->rmargin = p->maxrmargin;
 259      -                p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE);
      268 +                p->trailspace = 0;
      269 +                p->flags &= ~TERMP_NOBREAK;
 260  270                  p->flags |= TERMP_NOSPACE;
 261  271          }
 262  272  
 263  273          return(0);
 264  274  }
 265  275  
 266  276  /* ARGSUSED */
 267  277  static int
      278 +pre_PD(DECL_ARGS)
      279 +{
      280 +
      281 +        n = n->child;
      282 +        if (0 == n) {
      283 +                mt->pardist = 1;
      284 +                return(0);
      285 +        }
      286 +        assert(MAN_TEXT == n->type);
      287 +        mt->pardist = atoi(n->string);
      288 +        return(0);
      289 +}
      290 +
      291 +/* ARGSUSED */
      292 +static int
 268  293  pre_alternate(DECL_ARGS)
 269  294  {
 270  295          enum termfont            font[2];
 271  296          const struct man_node   *nn;
 272  297          int                      savelit, i;
 273  298  
 274  299          switch (n->tok) {
 275  300          case (MAN_RB):
 276  301                  font[0] = TERMFONT_NONE;
 277  302                  font[1] = TERMFONT_BOLD;
↓ open down ↓ 22 lines elided ↑ open up ↑
 300  325                  abort();
 301  326          }
 302  327  
 303  328          savelit = MANT_LITERAL & mt->fl;
 304  329          mt->fl &= ~MANT_LITERAL;
 305  330  
 306  331          for (i = 0, nn = n->child; nn; nn = nn->next, i = 1 - i) {
 307  332                  term_fontrepl(p, font[i]);
 308  333                  if (savelit && NULL == nn->next)
 309  334                          mt->fl |= MANT_LITERAL;
 310      -                print_man_node(p, mt, nn, m);
      335 +                print_man_node(p, mt, nn, meta);
 311  336                  if (nn->next)
 312  337                          p->flags |= TERMP_NOSPACE;
 313  338          }
 314  339  
 315  340          return(0);
 316  341  }
 317  342  
 318  343  /* ARGSUSED */
 319  344  static int
 320  345  pre_B(DECL_ARGS)
↓ open down ↓ 110 lines elided ↑ open up ↑
 431  456                  p->offset = p->rmargin;
 432  457  
 433  458          return(0);
 434  459  }
 435  460  
 436  461  
 437  462  /* ARGSUSED */
 438  463  static int
 439  464  pre_sp(DECL_ARGS)
 440  465  {
      466 +        char            *s;
 441  467          size_t           i, len;
      468 +        int              neg;
 442  469  
 443  470          if ((NULL == n->prev && n->parent)) {
 444      -                if (MAN_SS == n->parent->tok)
      471 +                switch (n->parent->tok) {
      472 +                case (MAN_SH):
      473 +                        /* FALLTHROUGH */
      474 +                case (MAN_SS):
      475 +                        /* FALLTHROUGH */
      476 +                case (MAN_PP):
      477 +                        /* FALLTHROUGH */
      478 +                case (MAN_LP):
      479 +                        /* FALLTHROUGH */
      480 +                case (MAN_P):
      481 +                        /* FALLTHROUGH */
 445  482                          return(0);
 446      -                if (MAN_SH == n->parent->tok)
 447      -                        return(0);
      483 +                default:
      484 +                        break;
      485 +                }
 448  486          }
 449  487  
      488 +        neg = 0;
 450  489          switch (n->tok) {
 451  490          case (MAN_br):
 452  491                  len = 0;
 453  492                  break;
 454  493          default:
 455      -                len = n->child ? a2height(p, n->child->string) : 1;
      494 +                if (NULL == n->child) {
      495 +                        len = 1;
      496 +                        break;
      497 +                }
      498 +                s = n->child->string;
      499 +                if ('-' == *s) {
      500 +                        neg = 1;
      501 +                        s++;
      502 +                }
      503 +                len = a2height(p, s);
 456  504                  break;
 457  505          }
 458  506  
 459  507          if (0 == len)
 460  508                  term_newln(p);
 461      -        for (i = 0; i < len; i++)
 462      -                term_vspace(p);
      509 +        else if (neg)
      510 +                p->skipvsp += len;
      511 +        else
      512 +                for (i = 0; i < len; i++)
      513 +                        term_vspace(p);
 463  514  
 464  515          return(0);
 465  516  }
 466  517  
 467  518  
 468  519  /* ARGSUSED */
 469  520  static int
 470  521  pre_HP(DECL_ARGS)
 471  522  {
 472  523          size_t                   len, one;
 473  524          int                      ival;
 474  525          const struct man_node   *nn;
 475  526  
 476  527          switch (n->type) {
 477  528          case (MAN_BLOCK):
 478      -                print_bvspace(p, n);
      529 +                print_bvspace(p, n, mt->pardist);
 479  530                  return(1);
 480  531          case (MAN_BODY):
 481      -                p->flags |= TERMP_NOBREAK;
 482      -                p->flags |= TERMP_TWOSPACE;
 483  532                  break;
 484  533          default:
 485  534                  return(0);
 486  535          }
 487  536  
      537 +        if ( ! (MANT_LITERAL & mt->fl)) {
      538 +                p->flags |= TERMP_NOBREAK;
      539 +                p->trailspace = 2;
      540 +        }
      541 +
 488  542          len = mt->lmargin[mt->lmargincur];
 489  543          ival = -1;
 490  544  
 491  545          /* Calculate offset. */
 492  546  
 493  547          if (NULL != (nn = n->parent->head->child))
 494  548                  if ((ival = a2width(p, nn->string)) >= 0)
 495  549                          len = (size_t)ival;
 496  550  
 497  551          one = term_len(p, 1);
↓ open down ↓ 9 lines elided ↑ open up ↑
 507  561          return(1);
 508  562  }
 509  563  
 510  564  
 511  565  /* ARGSUSED */
 512  566  static void
 513  567  post_HP(DECL_ARGS)
 514  568  {
 515  569  
 516  570          switch (n->type) {
 517      -        case (MAN_BLOCK):
 518      -                term_flushln(p);
 519      -                break;
 520  571          case (MAN_BODY):
 521      -                term_flushln(p);
      572 +                term_newln(p);
 522  573                  p->flags &= ~TERMP_NOBREAK;
 523      -                p->flags &= ~TERMP_TWOSPACE;
      574 +                p->trailspace = 0;
 524  575                  p->offset = mt->offset;
 525  576                  p->rmargin = p->maxrmargin;
 526  577                  break;
 527  578          default:
 528  579                  break;
 529  580          }
 530  581  }
 531  582  
 532  583  
 533  584  /* ARGSUSED */
 534  585  static int
 535  586  pre_PP(DECL_ARGS)
 536  587  {
 537  588  
 538  589          switch (n->type) {
 539  590          case (MAN_BLOCK):
 540  591                  mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
 541      -                print_bvspace(p, n);
      592 +                print_bvspace(p, n, mt->pardist);
 542  593                  break;
 543  594          default:
 544  595                  p->offset = mt->offset;
 545  596                  break;
 546  597          }
 547  598  
 548  599          return(MAN_HEAD != n->type);
 549  600  }
 550  601  
 551  602  
↓ open down ↓ 4 lines elided ↑ open up ↑
 556  607          const struct man_node   *nn;
 557  608          size_t                   len;
 558  609          int                      savelit, ival;
 559  610  
 560  611          switch (n->type) {
 561  612          case (MAN_BODY):
 562  613                  p->flags |= TERMP_NOSPACE;
 563  614                  break;
 564  615          case (MAN_HEAD):
 565  616                  p->flags |= TERMP_NOBREAK;
      617 +                p->trailspace = 1;
 566  618                  break;
 567  619          case (MAN_BLOCK):
 568      -                print_bvspace(p, n);
      620 +                print_bvspace(p, n, mt->pardist);
 569  621                  /* FALLTHROUGH */
 570  622          default:
 571  623                  return(1);
 572  624          }
 573  625  
 574  626          len = mt->lmargin[mt->lmargincur];
 575  627          ival = -1;
 576  628  
 577  629          /* Calculate the offset from the optional second argument. */
 578  630          if (NULL != (nn = n->parent->head->child))
↓ open down ↓ 12 lines elided ↑ open up ↑
 591  643                  if (ival < 0)
 592  644                          break;
 593  645  
 594  646                  /* Set the saved left-margin. */
 595  647                  mt->lmargin[mt->lmargincur] = (size_t)ival;
 596  648  
 597  649                  savelit = MANT_LITERAL & mt->fl;
 598  650                  mt->fl &= ~MANT_LITERAL;
 599  651  
 600  652                  if (n->child)
 601      -                        print_man_node(p, mt, n->child, m);
      653 +                        print_man_node(p, mt, n->child, meta);
 602  654  
 603  655                  if (savelit)
 604  656                          mt->fl |= MANT_LITERAL;
 605  657  
 606  658                  return(0);
 607  659          case (MAN_BODY):
 608  660                  p->offset = mt->offset + len;
 609  661                  p->rmargin = p->maxrmargin;
 610  662                  break;
 611  663          default:
↓ open down ↓ 6 lines elided ↑ open up ↑
 618  670  
 619  671  /* ARGSUSED */
 620  672  static void
 621  673  post_IP(DECL_ARGS)
 622  674  {
 623  675  
 624  676          switch (n->type) {
 625  677          case (MAN_HEAD):
 626  678                  term_flushln(p);
 627  679                  p->flags &= ~TERMP_NOBREAK;
      680 +                p->trailspace = 0;
 628  681                  p->rmargin = p->maxrmargin;
 629  682                  break;
 630  683          case (MAN_BODY):
 631  684                  term_newln(p);
      685 +                p->offset = mt->offset;
 632  686                  break;
 633  687          default:
 634  688                  break;
 635  689          }
 636  690  }
 637  691  
 638  692  
 639  693  /* ARGSUSED */
 640  694  static int
 641  695  pre_TP(DECL_ARGS)
 642  696  {
 643  697          const struct man_node   *nn;
 644  698          size_t                   len;
 645  699          int                      savelit, ival;
 646  700  
 647  701          switch (n->type) {
 648  702          case (MAN_HEAD):
 649  703                  p->flags |= TERMP_NOBREAK;
      704 +                p->trailspace = 1;
 650  705                  break;
 651  706          case (MAN_BODY):
 652  707                  p->flags |= TERMP_NOSPACE;
 653  708                  break;
 654  709          case (MAN_BLOCK):
 655      -                print_bvspace(p, n);
      710 +                print_bvspace(p, n, mt->pardist);
 656  711                  /* FALLTHROUGH */
 657  712          default:
 658  713                  return(1);
 659  714          }
 660  715  
 661  716          len = (size_t)mt->lmargin[mt->lmargincur];
 662  717          ival = -1;
 663  718  
 664  719          /* Calculate offset. */
 665  720  
↓ open down ↓ 10 lines elided ↑ open up ↑
 676  731  
 677  732                  p->offset = mt->offset;
 678  733                  p->rmargin = mt->offset + len;
 679  734  
 680  735                  savelit = MANT_LITERAL & mt->fl;
 681  736                  mt->fl &= ~MANT_LITERAL;
 682  737  
 683  738                  /* Don't print same-line elements. */
 684  739                  for (nn = n->child; nn; nn = nn->next)
 685  740                          if (nn->line > n->line)
 686      -                                print_man_node(p, mt, nn, m);
      741 +                                print_man_node(p, mt, nn, meta);
 687  742  
 688  743                  if (savelit)
 689  744                          mt->fl |= MANT_LITERAL;
 690  745                  if (ival >= 0)
 691  746                          mt->lmargin[mt->lmargincur] = (size_t)ival;
 692  747  
 693  748                  return(0);
 694  749          case (MAN_BODY):
 695  750                  p->offset = mt->offset + len;
 696  751                  p->rmargin = p->maxrmargin;
      752 +                p->trailspace = 0;
      753 +                p->flags &= ~TERMP_NOBREAK;
 697  754                  break;
 698  755          default:
 699  756                  break;
 700  757          }
 701  758  
 702  759          return(1);
 703  760  }
 704  761  
 705  762  
 706  763  /* ARGSUSED */
 707  764  static void
 708  765  post_TP(DECL_ARGS)
 709  766  {
 710  767  
 711  768          switch (n->type) {
 712  769          case (MAN_HEAD):
 713  770                  term_flushln(p);
 714      -                p->flags &= ~TERMP_NOBREAK;
 715      -                p->flags &= ~TERMP_TWOSPACE;
 716      -                p->rmargin = p->maxrmargin;
 717  771                  break;
 718  772          case (MAN_BODY):
 719  773                  term_newln(p);
      774 +                p->offset = mt->offset;
 720  775                  break;
 721  776          default:
 722  777                  break;
 723  778          }
 724  779  }
 725  780  
 726  781  
 727  782  /* ARGSUSED */
 728  783  static int
 729  784  pre_SS(DECL_ARGS)
 730  785  {
      786 +        int      i;
 731  787  
 732  788          switch (n->type) {
 733  789          case (MAN_BLOCK):
 734  790                  mt->fl &= ~MANT_LITERAL;
 735  791                  mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
 736  792                  mt->offset = term_len(p, p->defindent);
 737  793                  /* If following a prior empty `SS', no vspace. */
 738  794                  if (n->prev && MAN_SS == n->prev->tok)
 739  795                          if (NULL == n->prev->body->child)
 740  796                                  break;
 741  797                  if (NULL == n->prev)
 742  798                          break;
 743      -                term_vspace(p);
      799 +                for (i = 0; i < mt->pardist; i++)
      800 +                        term_vspace(p);
 744  801                  break;
 745  802          case (MAN_HEAD):
 746  803                  term_fontrepl(p, TERMFONT_BOLD);
 747      -                p->offset = term_len(p, p->defindent/2);
      804 +                p->offset = term_len(p, 3);
 748  805                  break;
 749  806          case (MAN_BODY):
 750  807                  p->offset = mt->offset;
 751  808                  break;
 752  809          default:
 753  810                  break;
 754  811          }
 755  812  
 756  813          return(1);
 757  814  }
↓ open down ↓ 14 lines elided ↑ open up ↑
 772  829          default:
 773  830                  break;
 774  831          }
 775  832  }
 776  833  
 777  834  
 778  835  /* ARGSUSED */
 779  836  static int
 780  837  pre_SH(DECL_ARGS)
 781  838  {
      839 +        int      i;
 782  840  
 783  841          switch (n->type) {
 784  842          case (MAN_BLOCK):
 785  843                  mt->fl &= ~MANT_LITERAL;
 786  844                  mt->lmargin[mt->lmargincur] = term_len(p, p->defindent);
 787  845                  mt->offset = term_len(p, p->defindent);
 788  846                  /* If following a prior empty `SH', no vspace. */
 789  847                  if (n->prev && MAN_SH == n->prev->tok)
 790  848                          if (NULL == n->prev->body->child)
 791  849                                  break;
 792  850                  /* If the first macro, no vspae. */
 793  851                  if (NULL == n->prev)
 794  852                          break;
 795      -                term_vspace(p);
      853 +                for (i = 0; i < mt->pardist; i++)
      854 +                        term_vspace(p);
 796  855                  break;
 797  856          case (MAN_HEAD):
 798  857                  term_fontrepl(p, TERMFONT_BOLD);
 799  858                  p->offset = 0;
 800  859                  break;
 801  860          case (MAN_BODY):
 802  861                  p->offset = mt->offset;
 803  862                  break;
 804  863          default:
 805  864                  break;
↓ open down ↓ 77 lines elided ↑ open up ↑
 883  942                  if ((ival = a2width(p, n->string)) >= 0) 
 884  943                          sz = (size_t)ival;
 885  944  
 886  945          mt->offset = mt->offset < sz ?  0 : mt->offset - sz;
 887  946          p->offset = mt->offset;
 888  947  
 889  948          if (--mt->lmarginsz < MAXMARGINS)
 890  949                  mt->lmargincur = mt->lmarginsz;
 891  950  }
 892  951  
      952 +/* ARGSUSED */
      953 +static int
      954 +pre_UR(DECL_ARGS)
      955 +{
      956 +
      957 +        return (MAN_HEAD != n->type);
      958 +}
      959 +
      960 +/* ARGSUSED */
 893  961  static void
      962 +post_UR(DECL_ARGS)
      963 +{
      964 +
      965 +        if (MAN_BLOCK != n->type)
      966 +                return;
      967 +
      968 +        term_word(p, "<");
      969 +        p->flags |= TERMP_NOSPACE;
      970 +
      971 +        if (NULL != n->child->child)
      972 +                print_man_node(p, mt, n->child->child, meta);
      973 +
      974 +        p->flags |= TERMP_NOSPACE;
      975 +        term_word(p, ">");
      976 +}
      977 +
      978 +static void
 894  979  print_man_node(DECL_ARGS)
 895  980  {
 896  981          size_t           rm, rmax;
 897  982          int              c;
 898  983  
 899  984          switch (n->type) {
 900  985          case(MAN_TEXT):
 901  986                  /*
 902  987                   * If we have a blank line, output a vertical space.
 903  988                   * If we have a space as the first character, break
 904  989                   * before printing the line's data.
 905  990                   */
 906  991                  if ('\0' == *n->string) {
 907  992                          term_vspace(p);
 908  993                          return;
 909  994                  } else if (' ' == *n->string && MAN_LINE & n->flags)
 910  995                          term_newln(p);
 911  996  
 912  997                  term_word(p, n->string);
      998 +                goto out;
 913  999  
 914      -                /*
 915      -                 * If we're in a literal context, make sure that words
 916      -                 * togehter on the same line stay together.  This is a
 917      -                 * POST-printing call, so we check the NEXT word.  Since
 918      -                 * -man doesn't have nested macros, we don't need to be
 919      -                 * more specific than this.
 920      -                 */
 921      -                if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
 922      -                                (NULL == n->next || 
 923      -                                 n->next->line > n->line)) {
 924      -                        rm = p->rmargin;
 925      -                        rmax = p->maxrmargin;
 926      -                        p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
 927      -                        p->flags |= TERMP_NOSPACE;
 928      -                        term_flushln(p);
 929      -                        p->rmargin = rm;
 930      -                        p->maxrmargin = rmax;
 931      -                }
 932      -
 933      -                if (MAN_EOS & n->flags)
 934      -                        p->flags |= TERMP_SENTENCE;
 935      -                return;
 936 1000          case (MAN_EQN):
 937 1001                  term_eqn(p, n->eqn);
 938 1002                  return;
 939 1003          case (MAN_TBL):
 940 1004                  /*
 941 1005                   * Tables are preceded by a newline.  Then process a
 942 1006                   * table line, which will cause line termination,
 943 1007                   */
 944 1008                  if (TBL_SPAN_FIRST & n->span->flags) 
 945 1009                          term_newln(p);
↓ open down ↓ 1 lines elided ↑ open up ↑
 947 1011                  return;
 948 1012          default:
 949 1013                  break;
 950 1014          }
 951 1015  
 952 1016          if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
 953 1017                  term_fontrepl(p, TERMFONT_NONE);
 954 1018  
 955 1019          c = 1;
 956 1020          if (termacts[n->tok].pre)
 957      -                c = (*termacts[n->tok].pre)(p, mt, n, m);
     1021 +                c = (*termacts[n->tok].pre)(p, mt, n, meta);
 958 1022  
 959 1023          if (c && n->child)
 960      -                print_man_nodelist(p, mt, n->child, m);
     1024 +                print_man_nodelist(p, mt, n->child, meta);
 961 1025  
 962 1026          if (termacts[n->tok].post)
 963      -                (*termacts[n->tok].post)(p, mt, n, m);
     1027 +                (*termacts[n->tok].post)(p, mt, n, meta);
 964 1028          if ( ! (MAN_NOTEXT & termacts[n->tok].flags))
 965 1029                  term_fontrepl(p, TERMFONT_NONE);
 966 1030  
     1031 +out:
     1032 +        /*
     1033 +         * If we're in a literal context, make sure that words
     1034 +         * together on the same line stay together.  This is a
     1035 +         * POST-printing call, so we check the NEXT word.  Since
     1036 +         * -man doesn't have nested macros, we don't need to be
     1037 +         * more specific than this.
     1038 +         */
     1039 +        if (MANT_LITERAL & mt->fl && ! (TERMP_NOBREAK & p->flags) &&
     1040 +            (NULL == n->next || n->next->line > n->line)) {
     1041 +                rm = p->rmargin;
     1042 +                rmax = p->maxrmargin;
     1043 +                p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
     1044 +                p->flags |= TERMP_NOSPACE;
     1045 +                if (NULL != n->string && '\0' != *n->string)
     1046 +                        term_flushln(p);
     1047 +                else
     1048 +                        term_newln(p);
     1049 +                if (rm < rmax && n->parent->tok == MAN_HP) {
     1050 +                        p->offset = rm;
     1051 +                        p->rmargin = rmax;
     1052 +                } else
     1053 +                        p->rmargin = rm;
     1054 +                p->maxrmargin = rmax;
     1055 +        }
 967 1056          if (MAN_EOS & n->flags)
 968 1057                  p->flags |= TERMP_SENTENCE;
 969 1058  }
 970 1059  
 971 1060  
 972 1061  static void
 973 1062  print_man_nodelist(DECL_ARGS)
 974 1063  {
 975 1064  
 976      -        print_man_node(p, mt, n, m);
     1065 +        print_man_node(p, mt, n, meta);
 977 1066          if ( ! n->next)
 978 1067                  return;
 979      -        print_man_nodelist(p, mt, n->next, m);
     1068 +        print_man_nodelist(p, mt, n->next, meta);
 980 1069  }
 981 1070  
 982 1071  
 983 1072  static void
 984 1073  print_man_foot(struct termp *p, const void *arg)
 985 1074  {
 986 1075          char            title[BUFSIZ];
 987 1076          size_t          datelen;
 988 1077          const struct man_meta *meta;
 989 1078  
↓ open down ↓ 19 lines elided ↑ open up ↑
1009 1098          } else if (meta->source) {
1010 1099                  strlcpy(title, meta->source, BUFSIZ);
1011 1100          } else {
1012 1101                  title[0] = '\0';
1013 1102          }
1014 1103          datelen = term_strlen(p, meta->date);
1015 1104  
1016 1105          /* Bottom left corner: manual source. */
1017 1106  
1018 1107          p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
     1108 +        p->trailspace = 1;
1019 1109          p->offset = 0;
1020 1110          p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
1021 1111  
1022 1112          if (meta->source)
1023 1113                  term_word(p, meta->source);
1024 1114          term_flushln(p);
1025 1115  
1026 1116          /* At the bottom in the middle: manual date. */
1027 1117  
1028 1118          p->flags |= TERMP_NOSPACE;
↓ open down ↓ 2 lines elided ↑ open up ↑
1031 1121          if (p->offset + datelen >= p->rmargin)
1032 1122                  p->rmargin = p->offset + datelen;
1033 1123  
1034 1124          term_word(p, meta->date);
1035 1125          term_flushln(p);
1036 1126  
1037 1127          /* Bottom right corner: manual title and section. */
1038 1128  
1039 1129          p->flags &= ~TERMP_NOBREAK;
1040 1130          p->flags |= TERMP_NOSPACE;
     1131 +        p->trailspace = 0;
1041 1132          p->offset = p->rmargin;
1042 1133          p->rmargin = p->maxrmargin;
1043 1134  
1044 1135          term_word(p, title);
1045 1136          term_flushln(p);
1046 1137  }
1047 1138  
1048 1139  
1049 1140  static void
1050 1141  print_man_head(struct termp *p, const void *arg)
1051 1142  {
1052 1143          char            buf[BUFSIZ], title[BUFSIZ];
1053 1144          size_t          buflen, titlen;
1054      -        const struct man_meta *m;
     1145 +        const struct man_meta *meta;
1055 1146  
1056      -        m = (const struct man_meta *)arg;
1057      -        assert(m->title);
1058      -        assert(m->msec);
     1147 +        meta = (const struct man_meta *)arg;
     1148 +        assert(meta->title);
     1149 +        assert(meta->msec);
1059 1150  
1060      -        if (m->vol)
1061      -                strlcpy(buf, m->vol, BUFSIZ);
     1151 +        if (meta->vol)
     1152 +                strlcpy(buf, meta->vol, BUFSIZ);
1062 1153          else
1063 1154                  buf[0] = '\0';
1064 1155          buflen = term_strlen(p, buf);
1065 1156  
1066 1157          /* Top left corner: manual title and section. */
1067 1158  
1068      -        snprintf(title, BUFSIZ, "%s(%s)", m->title, m->msec);
     1159 +        snprintf(title, BUFSIZ, "%s(%s)", meta->title, meta->msec);
1069 1160          titlen = term_strlen(p, title);
1070 1161  
1071 1162          p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
     1163 +        p->trailspace = 1;
1072 1164          p->offset = 0;
1073 1165          p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
1074 1166              (p->maxrmargin - 
1075 1167               term_strlen(p, buf) + term_len(p, 1)) / 2 :
1076 1168              p->maxrmargin - buflen;
1077 1169  
1078 1170          term_word(p, title);
1079 1171          term_flushln(p);
1080 1172  
1081 1173          /* At the top in the middle: manual volume. */
↓ open down ↓ 2 lines elided ↑ open up ↑
1084 1176          p->offset = p->rmargin;
1085 1177          p->rmargin = p->offset + buflen + titlen < p->maxrmargin ?
1086 1178              p->maxrmargin - titlen : p->maxrmargin;
1087 1179  
1088 1180          term_word(p, buf);
1089 1181          term_flushln(p);
1090 1182  
1091 1183          /* Top right corner: title and section, again. */
1092 1184  
1093 1185          p->flags &= ~TERMP_NOBREAK;
     1186 +        p->trailspace = 0;
1094 1187          if (p->rmargin + titlen <= p->maxrmargin) {
1095 1188                  p->flags |= TERMP_NOSPACE;
1096 1189                  p->offset = p->rmargin;
1097 1190                  p->rmargin = p->maxrmargin;
1098 1191                  term_word(p, title);
1099 1192                  term_flushln(p);
1100 1193          }
1101 1194  
1102 1195          p->flags &= ~TERMP_NOSPACE;
1103 1196          p->offset = 0;
↓ open down ↓ 14 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX