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/tbl_term.c
          +++ new/usr/src/cmd/mandoc/tbl_term.c
   1      -/*      $Id: tbl_term.c,v 1.21 2011/09/20 23:05:49 schwarze Exp $ */
        1 +/*      $Id: tbl_term.c,v 1.25 2013/05/31 21:37:17 schwarze Exp $ */
   2    2  /*
   3    3   * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
   4      - * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
        4 + * Copyright (c) 2011, 2012 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 ↓ 9 lines elided ↑ open up ↑
  24   24  #include <stdlib.h>
  25   25  #include <string.h>
  26   26  
  27   27  #include "mandoc.h"
  28   28  #include "out.h"
  29   29  #include "term.h"
  30   30  
  31   31  static  size_t  term_tbl_len(size_t, void *);
  32   32  static  size_t  term_tbl_strlen(const char *, void *);
  33   33  static  void    tbl_char(struct termp *, char, size_t);
  34      -static  void    tbl_data(struct termp *, const struct tbl *,
       34 +static  void    tbl_data(struct termp *, const struct tbl_opts *,
  35   35                          const struct tbl_dat *, 
  36   36                          const struct roffcol *);
  37   37  static  size_t  tbl_rulewidth(struct termp *, const struct tbl_head *);
  38   38  static  void    tbl_hframe(struct termp *, const struct tbl_span *, int);
  39   39  static  void    tbl_literal(struct termp *, const struct tbl_dat *, 
  40   40                          const struct roffcol *);
  41      -static  void    tbl_number(struct termp *, const struct tbl *, 
       41 +static  void    tbl_number(struct termp *, const struct tbl_opts *, 
  42   42                          const struct tbl_dat *, 
  43   43                          const struct roffcol *);
  44   44  static  void    tbl_hrule(struct termp *, const struct tbl_span *);
  45   45  static  void    tbl_vrule(struct termp *, const struct tbl_head *);
  46   46  
  47   47  
  48   48  static size_t
  49   49  term_tbl_strlen(const char *p, void *arg)
  50   50  {
  51   51  
↓ open down ↓ 37 lines elided ↑ open up ↑
  89   89                  tp->tbl.len = term_tbl_len;
  90   90                  tp->tbl.slen = term_tbl_strlen;
  91   91                  tp->tbl.arg = tp;
  92   92  
  93   93                  tblcalc(&tp->tbl, sp);
  94   94          }
  95   95  
  96   96          /* Horizontal frame at the start of boxed tables. */
  97   97  
  98   98          if (TBL_SPAN_FIRST & sp->flags) {
  99      -                if (TBL_OPT_DBOX & sp->tbl->opts)
       99 +                if (TBL_OPT_DBOX & sp->opts->opts)
 100  100                          tbl_hframe(tp, sp, 1);
 101      -                if (TBL_OPT_DBOX & sp->tbl->opts ||
 102      -                    TBL_OPT_BOX  & sp->tbl->opts)
      101 +                if (TBL_OPT_DBOX & sp->opts->opts ||
      102 +                    TBL_OPT_BOX  & sp->opts->opts)
 103  103                          tbl_hframe(tp, sp, 0);
 104  104          }
 105  105  
 106  106          /* Vertical frame at the start of each row. */
 107  107  
 108      -        if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)
      108 +        if (TBL_OPT_BOX & sp->opts->opts || TBL_OPT_DBOX & sp->opts->opts)
 109  109                  term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
 110  110                          TBL_SPAN_DHORIZ == sp->pos ? "+" : "|");
 111  111  
 112  112          /*
 113  113           * Now print the actual data itself depending on the span type.
 114  114           * Spanner spans get a horizontal rule; data spanners have their
 115  115           * data printed by matching data to header.
 116  116           */
 117  117  
 118  118          switch (sp->pos) {
 119  119          case (TBL_SPAN_HORIZ):
 120  120                  /* FALLTHROUGH */
 121  121          case (TBL_SPAN_DHORIZ):
 122  122                  tbl_hrule(tp, sp);
 123  123                  break;
 124  124          case (TBL_SPAN_DATA):
 125  125                  /* Iterate over template headers. */
 126  126                  dp = sp->first;
 127  127                  spans = 0;
 128  128                  for (hp = sp->head; hp; hp = hp->next) {
      129 +
 129  130                          /* 
 130  131                           * If the current data header is invoked during
 131  132                           * a spanner ("spans" > 0), don't emit anything
 132  133                           * at all.
 133  134                           */
 134      -                        switch (hp->pos) {
 135      -                        case (TBL_HEAD_VERT):
 136      -                                /* FALLTHROUGH */
 137      -                        case (TBL_HEAD_DVERT):
 138      -                                if (spans <= 0)
 139      -                                        tbl_vrule(tp, hp);
 140      -                                continue;
 141      -                        case (TBL_HEAD_DATA):
 142      -                                break;
 143      -                        }
 144  135  
 145  136                          if (--spans >= 0)
 146  137                                  continue;
 147  138  
 148      -                        /*
 149      -                         * All cells get a leading blank, except the
 150      -                         * first one and those after double rulers.
 151      -                         */
      139 +                        /* Separate columns. */
 152  140  
 153      -                        if (hp->prev && TBL_HEAD_DVERT != hp->prev->pos)
 154      -                                tbl_char(tp, ASCII_NBRSP, 1);
      141 +                        if (NULL != hp->prev)
      142 +                                tbl_vrule(tp, hp);
 155  143  
 156  144                          col = &tp->tbl.cols[hp->ident];
 157      -                        tbl_data(tp, sp->tbl, dp, col);
      145 +                        tbl_data(tp, sp->opts, dp, col);
 158  146  
 159      -                        /* No trailing blanks. */
 160      -
 161      -                        if (NULL == hp->next)
 162      -                                break;
 163      -
 164      -                        /*
 165      -                         * Add another blank between cells,
 166      -                         * or two when there is no vertical ruler.
 167      -                         */
 168      -
 169      -                        tbl_char(tp, ASCII_NBRSP,
 170      -                            TBL_HEAD_VERT  == hp->next->pos ||
 171      -                            TBL_HEAD_DVERT == hp->next->pos ? 1 : 2);
 172      -
 173  147                          /* 
 174  148                           * Go to the next data cell and assign the
 175  149                           * number of subsequent spans, if applicable.
 176  150                           */
 177  151  
 178  152                          if (dp) {
 179  153                                  spans = dp->spans;
 180  154                                  dp = dp->next;
 181  155                          }
 182  156                  }
 183  157                  break;
 184  158          }
 185  159  
 186  160          /* Vertical frame at the end of each row. */
 187  161  
 188      -        if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)
      162 +        if (TBL_OPT_BOX & sp->opts->opts || TBL_OPT_DBOX & sp->opts->opts)
 189  163                  term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
 190  164                          TBL_SPAN_DHORIZ == sp->pos ? "+" : " |");
 191  165          term_flushln(tp);
 192  166  
 193  167          /*
 194  168           * If we're the last row, clean up after ourselves: clear the
 195  169           * existing table configuration and set it to NULL.
 196  170           */
 197  171  
 198  172          if (TBL_SPAN_LAST & sp->flags) {
 199      -                if (TBL_OPT_DBOX & sp->tbl->opts ||
 200      -                    TBL_OPT_BOX  & sp->tbl->opts)
      173 +                if (TBL_OPT_DBOX & sp->opts->opts ||
      174 +                    TBL_OPT_BOX  & sp->opts->opts) {
 201  175                          tbl_hframe(tp, sp, 0);
 202      -                if (TBL_OPT_DBOX & sp->tbl->opts)
      176 +                        tp->skipvsp = 1;
      177 +                }
      178 +                if (TBL_OPT_DBOX & sp->opts->opts) {
 203  179                          tbl_hframe(tp, sp, 1);
      180 +                        tp->skipvsp = 2;
      181 +                }
 204  182                  assert(tp->tbl.cols);
 205  183                  free(tp->tbl.cols);
 206  184                  tp->tbl.cols = NULL;
 207  185          }
 208  186  
 209  187          tp->flags &= ~TERMP_NONOSPACE;
 210  188          tp->rmargin = rmargin;
 211  189          tp->maxrmargin = maxrmargin;
 212  190  
 213  191  }
↓ open down ↓ 1 lines elided ↑ open up ↑
 215  193  /*
 216  194   * Horizontal rules extend across the entire table.
 217  195   * Calculate the width by iterating over columns.
 218  196   */
 219  197  static size_t
 220  198  tbl_rulewidth(struct termp *tp, const struct tbl_head *hp)
 221  199  {
 222  200          size_t           width;
 223  201  
 224  202          width = tp->tbl.cols[hp->ident].width;
 225      -        if (TBL_HEAD_DATA == hp->pos) {
 226      -                /* Account for leading blanks. */
 227      -                if (hp->prev && TBL_HEAD_DVERT != hp->prev->pos)
 228      -                        width++;
 229      -                /* Account for trailing blanks. */
 230      -                width++;
 231      -                if (hp->next &&
 232      -                    TBL_HEAD_VERT  != hp->next->pos &&
 233      -                    TBL_HEAD_DVERT != hp->next->pos)
 234      -                        width++;
 235      -        }
      203 +
      204 +        /* Account for leading blanks. */
      205 +        if (hp->prev)
      206 +                width += 2 - hp->vert;
      207 +
      208 +        /* Account for trailing blank. */
      209 +        width++;
      210 +
 236  211          return(width);
 237  212  }
 238  213  
 239  214  /*
 240  215   * Rules inside the table can be single or double
 241  216   * and have crossings with vertical rules marked with pluses.
 242  217   */
 243  218  static void
 244  219  tbl_hrule(struct termp *tp, const struct tbl_span *sp)
 245  220  {
 246  221          const struct tbl_head *hp;
 247  222          char             c;
 248  223  
 249  224          c = '-';
 250  225          if (TBL_SPAN_DHORIZ == sp->pos)
 251  226                  c = '=';
 252  227  
 253      -        for (hp = sp->head; hp; hp = hp->next)
 254      -                tbl_char(tp,
 255      -                    TBL_HEAD_DATA == hp->pos ? c : '+',
 256      -                    tbl_rulewidth(tp, hp));
      228 +        for (hp = sp->head; hp; hp = hp->next) {
      229 +                if (hp->prev && hp->vert)
      230 +                        tbl_char(tp, '+', hp->vert);
      231 +                tbl_char(tp, c, tbl_rulewidth(tp, hp));
      232 +        }
 257  233  }
 258  234  
 259  235  /*
 260  236   * Rules above and below the table are always single
 261  237   * and have an additional plus at the beginning and end.
 262  238   * For double frames, this function is called twice,
 263  239   * and the outer one does not have crossings.
 264  240   */
 265  241  static void
 266  242  tbl_hframe(struct termp *tp, const struct tbl_span *sp, int outer)
 267  243  {
 268  244          const struct tbl_head *hp;
 269  245  
 270  246          term_word(tp, "+");
 271      -        for (hp = sp->head; hp; hp = hp->next)
 272      -                tbl_char(tp,
 273      -                    outer || TBL_HEAD_DATA == hp->pos ? '-' : '+',
 274      -                    tbl_rulewidth(tp, hp));
      247 +        for (hp = sp->head; hp; hp = hp->next) {
      248 +                if (hp->prev && hp->vert)
      249 +                        tbl_char(tp, (outer ? '-' : '+'), hp->vert);
      250 +                tbl_char(tp, '-', tbl_rulewidth(tp, hp));
      251 +        }
 275  252          term_word(tp, "+");
 276  253          term_flushln(tp);
 277  254  }
 278  255  
 279  256  static void
 280      -tbl_data(struct termp *tp, const struct tbl *tbl,
      257 +tbl_data(struct termp *tp, const struct tbl_opts *opts,
 281  258                  const struct tbl_dat *dp, 
 282  259                  const struct roffcol *col)
 283  260  {
 284  261  
 285  262          if (NULL == dp) {
 286  263                  tbl_char(tp, ASCII_NBRSP, col->width);
 287  264                  return;
 288  265          }
 289  266          assert(dp->layout);
 290  267  
↓ open down ↓ 25 lines elided ↑ open up ↑
 316  293          case (TBL_CELL_LONG):
 317  294                  /* FALLTHROUGH */
 318  295          case (TBL_CELL_CENTRE):
 319  296                  /* FALLTHROUGH */
 320  297          case (TBL_CELL_LEFT):
 321  298                  /* FALLTHROUGH */
 322  299          case (TBL_CELL_RIGHT):
 323  300                  tbl_literal(tp, dp, col);
 324  301                  break;
 325  302          case (TBL_CELL_NUMBER):
 326      -                tbl_number(tp, tbl, dp, col);
      303 +                tbl_number(tp, opts, dp, col);
 327  304                  break;
 328  305          case (TBL_CELL_DOWN):
 329  306                  tbl_char(tp, ASCII_NBRSP, col->width);
 330  307                  break;
 331  308          default:
 332  309                  abort();
 333  310                  /* NOTREACHED */
 334  311          }
 335  312  }
 336  313  
 337  314  static void
 338  315  tbl_vrule(struct termp *tp, const struct tbl_head *hp)
 339  316  {
 340  317  
 341      -        switch (hp->pos) {
 342      -        case (TBL_HEAD_VERT):
 343      -                term_word(tp, "|");
 344      -                break;
 345      -        case (TBL_HEAD_DVERT):
 346      -                term_word(tp, "||");
 347      -                break;
 348      -        default:
 349      -                break;
 350      -        }
      318 +        tbl_char(tp, ASCII_NBRSP, 1);
      319 +        if (0 < hp->vert)
      320 +                tbl_char(tp, '|', hp->vert);
      321 +        if (2 > hp->vert)
      322 +                tbl_char(tp, ASCII_NBRSP, 2 - hp->vert);
 351  323  }
 352  324  
 353  325  static void
 354  326  tbl_char(struct termp *tp, char c, size_t len)
 355  327  {
 356  328          size_t          i, sz;
 357  329          char            cp[2];
 358  330  
 359  331          cp[0] = c;
 360  332          cp[1] = '\0';
↓ open down ↓ 1 lines elided ↑ open up ↑
 362  334          sz = term_strlen(tp, cp);
 363  335  
 364  336          for (i = 0; i < len; i += sz)
 365  337                  term_word(tp, cp);
 366  338  }
 367  339  
 368  340  static void
 369  341  tbl_literal(struct termp *tp, const struct tbl_dat *dp, 
 370  342                  const struct roffcol *col)
 371  343  {
 372      -        size_t           len, padl, padr;
      344 +        struct tbl_head         *hp;
      345 +        size_t                   width, len, padl, padr;
      346 +        int                      spans;
 373  347  
 374  348          assert(dp->string);
 375  349          len = term_strlen(tp, dp->string);
 376      -        padr = col->width > len ? col->width - len : 0;
      350 +
      351 +        hp = dp->layout->head->next;
      352 +        width = col->width;
      353 +        for (spans = dp->spans; spans--; hp = hp->next)
      354 +                width += tp->tbl.cols[hp->ident].width + 3;
      355 +
      356 +        padr = width > len ? width - len : 0;
 377  357          padl = 0;
 378  358  
 379  359          switch (dp->layout->pos) {
 380  360          case (TBL_CELL_LONG):
 381  361                  padl = term_len(tp, 1);
 382  362                  padr = padr > padl ? padr - padl : 0;
 383  363                  break;
 384  364          case (TBL_CELL_CENTRE):
 385  365                  if (2 > padr)
 386  366                          break;
↓ open down ↓ 7 lines elided ↑ open up ↑
 394  374          default:
 395  375                  break;
 396  376          }
 397  377  
 398  378          tbl_char(tp, ASCII_NBRSP, padl);
 399  379          term_word(tp, dp->string);
 400  380          tbl_char(tp, ASCII_NBRSP, padr);
 401  381  }
 402  382  
 403  383  static void
 404      -tbl_number(struct termp *tp, const struct tbl *tbl,
      384 +tbl_number(struct termp *tp, const struct tbl_opts *opts,
 405  385                  const struct tbl_dat *dp,
 406  386                  const struct roffcol *col)
 407  387  {
 408  388          char            *cp;
 409  389          char             buf[2];
 410  390          size_t           sz, psz, ssz, d, padl;
 411  391          int              i;
 412  392  
 413  393          /*
 414  394           * See calc_data_number().  Left-pad by taking the offset of our
 415  395           * and the maximum decimal; right-pad by the remaining amount.
 416  396           */
 417  397  
 418  398          assert(dp->string);
 419  399  
 420  400          sz = term_strlen(tp, dp->string);
 421  401  
 422      -        buf[0] = tbl->decimal;
      402 +        buf[0] = opts->decimal;
 423  403          buf[1] = '\0';
 424  404  
 425  405          psz = term_strlen(tp, buf);
 426  406  
 427      -        if (NULL != (cp = strrchr(dp->string, tbl->decimal))) {
      407 +        if (NULL != (cp = strrchr(dp->string, opts->decimal))) {
 428  408                  buf[1] = '\0';
 429  409                  for (ssz = 0, i = 0; cp != &dp->string[i]; i++) {
 430  410                          buf[0] = dp->string[i];
 431  411                          ssz += term_strlen(tp, buf);
 432  412                  }
 433  413                  d = ssz + psz;
 434  414          } else
 435  415                  d = sz + psz;
 436  416  
 437  417          padl = col->decimal - d;
 438  418  
 439  419          tbl_char(tp, ASCII_NBRSP, padl);
 440  420          term_word(tp, dp->string);
 441  421          if (col->width > sz + padl)
 442  422                  tbl_char(tp, ASCII_NBRSP, col->width - sz - padl);
 443  423  }
 444  424  
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX