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

@@ -1,9 +1,9 @@
-/*      $Id: tbl_term.c,v 1.21 2011/09/20 23:05:49 schwarze Exp $ */
+/*      $Id: tbl_term.c,v 1.25 2013/05/31 21:37:17 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
  *

@@ -29,18 +29,18 @@
 #include "term.h"
 
 static  size_t  term_tbl_len(size_t, void *);
 static  size_t  term_tbl_strlen(const char *, void *);
 static  void    tbl_char(struct termp *, char, size_t);
-static  void    tbl_data(struct termp *, const struct tbl *,
+static  void    tbl_data(struct termp *, const struct tbl_opts *,
                         const struct tbl_dat *, 
                         const struct roffcol *);
 static  size_t  tbl_rulewidth(struct termp *, const struct tbl_head *);
 static  void    tbl_hframe(struct termp *, const struct tbl_span *, int);
 static  void    tbl_literal(struct termp *, const struct tbl_dat *, 
                         const struct roffcol *);
-static  void    tbl_number(struct termp *, const struct tbl *, 
+static  void    tbl_number(struct termp *, const struct tbl_opts *, 
                         const struct tbl_dat *, 
                         const struct roffcol *);
 static  void    tbl_hrule(struct termp *, const struct tbl_span *);
 static  void    tbl_vrule(struct termp *, const struct tbl_head *);
 

@@ -94,20 +94,20 @@
         }
 
         /* Horizontal frame at the start of boxed tables. */
 
         if (TBL_SPAN_FIRST & sp->flags) {
-                if (TBL_OPT_DBOX & sp->tbl->opts)
+                if (TBL_OPT_DBOX & sp->opts->opts)
                         tbl_hframe(tp, sp, 1);
-                if (TBL_OPT_DBOX & sp->tbl->opts ||
-                    TBL_OPT_BOX  & sp->tbl->opts)
+                if (TBL_OPT_DBOX & sp->opts->opts ||
+                    TBL_OPT_BOX  & sp->opts->opts)
                         tbl_hframe(tp, sp, 0);
         }
 
         /* Vertical frame at the start of each row. */
 
-        if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)
+        if (TBL_OPT_BOX & sp->opts->opts || TBL_OPT_DBOX & sp->opts->opts)
                 term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
                         TBL_SPAN_DHORIZ == sp->pos ? "+" : "|");
 
         /*
          * Now print the actual data itself depending on the span type.

@@ -124,55 +124,29 @@
         case (TBL_SPAN_DATA):
                 /* Iterate over template headers. */
                 dp = sp->first;
                 spans = 0;
                 for (hp = sp->head; hp; hp = hp->next) {
+
                         /* 
                          * If the current data header is invoked during
                          * a spanner ("spans" > 0), don't emit anything
                          * at all.
                          */
-                        switch (hp->pos) {
-                        case (TBL_HEAD_VERT):
-                                /* FALLTHROUGH */
-                        case (TBL_HEAD_DVERT):
-                                if (spans <= 0)
-                                        tbl_vrule(tp, hp);
-                                continue;
-                        case (TBL_HEAD_DATA):
-                                break;
-                        }
 
                         if (--spans >= 0)
                                 continue;
 
-                        /*
-                         * All cells get a leading blank, except the
-                         * first one and those after double rulers.
-                         */
+                        /* Separate columns. */
 
-                        if (hp->prev && TBL_HEAD_DVERT != hp->prev->pos)
-                                tbl_char(tp, ASCII_NBRSP, 1);
+                        if (NULL != hp->prev)
+                                tbl_vrule(tp, hp);
 
                         col = &tp->tbl.cols[hp->ident];
-                        tbl_data(tp, sp->tbl, dp, col);
+                        tbl_data(tp, sp->opts, dp, col);
 
-                        /* No trailing blanks. */
-
-                        if (NULL == hp->next)
-                                break;
-
                         /*
-                         * Add another blank between cells,
-                         * or two when there is no vertical ruler.
-                         */
-
-                        tbl_char(tp, ASCII_NBRSP,
-                            TBL_HEAD_VERT  == hp->next->pos ||
-                            TBL_HEAD_DVERT == hp->next->pos ? 1 : 2);
-
-                        /* 
                          * Go to the next data cell and assign the
                          * number of subsequent spans, if applicable.
                          */
 
                         if (dp) {

@@ -183,11 +157,11 @@
                 break;
         }
 
         /* Vertical frame at the end of each row. */
 
-        if (TBL_OPT_BOX & sp->tbl->opts || TBL_OPT_DBOX & sp->tbl->opts)
+        if (TBL_OPT_BOX & sp->opts->opts || TBL_OPT_DBOX & sp->opts->opts)
                 term_word(tp, TBL_SPAN_HORIZ == sp->pos ||
                         TBL_SPAN_DHORIZ == sp->pos ? "+" : " |");
         term_flushln(tp);
 
         /*

@@ -194,15 +168,19 @@
          * If we're the last row, clean up after ourselves: clear the
          * existing table configuration and set it to NULL.
          */
 
         if (TBL_SPAN_LAST & sp->flags) {
-                if (TBL_OPT_DBOX & sp->tbl->opts ||
-                    TBL_OPT_BOX  & sp->tbl->opts)
+                if (TBL_OPT_DBOX & sp->opts->opts ||
+                    TBL_OPT_BOX  & sp->opts->opts) {
                         tbl_hframe(tp, sp, 0);
-                if (TBL_OPT_DBOX & sp->tbl->opts)
+                        tp->skipvsp = 1;
+                }
+                if (TBL_OPT_DBOX & sp->opts->opts) {
                         tbl_hframe(tp, sp, 1);
+                        tp->skipvsp = 2;
+                }
                 assert(tp->tbl.cols);
                 free(tp->tbl.cols);
                 tp->tbl.cols = NULL;
         }
 

@@ -220,21 +198,18 @@
 tbl_rulewidth(struct termp *tp, const struct tbl_head *hp)
 {
         size_t           width;
 
         width = tp->tbl.cols[hp->ident].width;
-        if (TBL_HEAD_DATA == hp->pos) {
+
                 /* Account for leading blanks. */
-                if (hp->prev && TBL_HEAD_DVERT != hp->prev->pos)
+        if (hp->prev)
+                width += 2 - hp->vert;
+
+        /* Account for trailing blank. */
                         width++;
-                /* Account for trailing blanks. */
-                width++;
-                if (hp->next &&
-                    TBL_HEAD_VERT  != hp->next->pos &&
-                    TBL_HEAD_DVERT != hp->next->pos)
-                        width++;
-        }
+
         return(width);
 }
 
 /*
  * Rules inside the table can be single or double

@@ -248,14 +223,15 @@
 
         c = '-';
         if (TBL_SPAN_DHORIZ == sp->pos)
                 c = '=';
 
-        for (hp = sp->head; hp; hp = hp->next)
-                tbl_char(tp,
-                    TBL_HEAD_DATA == hp->pos ? c : '+',
-                    tbl_rulewidth(tp, hp));
+        for (hp = sp->head; hp; hp = hp->next) {
+                if (hp->prev && hp->vert)
+                        tbl_char(tp, '+', hp->vert);
+                tbl_char(tp, c, tbl_rulewidth(tp, hp));
+        }
 }
 
 /*
  * Rules above and below the table are always single
  * and have an additional plus at the beginning and end.

@@ -266,20 +242,21 @@
 tbl_hframe(struct termp *tp, const struct tbl_span *sp, int outer)
 {
         const struct tbl_head *hp;
 
         term_word(tp, "+");
-        for (hp = sp->head; hp; hp = hp->next)
-                tbl_char(tp,
-                    outer || TBL_HEAD_DATA == hp->pos ? '-' : '+',
-                    tbl_rulewidth(tp, hp));
+        for (hp = sp->head; hp; hp = hp->next) {
+                if (hp->prev && hp->vert)
+                        tbl_char(tp, (outer ? '-' : '+'), hp->vert);
+                tbl_char(tp, '-', tbl_rulewidth(tp, hp));
+        }
         term_word(tp, "+");
         term_flushln(tp);
 }
 
 static void
-tbl_data(struct termp *tp, const struct tbl *tbl,
+tbl_data(struct termp *tp, const struct tbl_opts *opts,
                 const struct tbl_dat *dp, 
                 const struct roffcol *col)
 {
 
         if (NULL == dp) {

@@ -321,11 +298,11 @@
                 /* FALLTHROUGH */
         case (TBL_CELL_RIGHT):
                 tbl_literal(tp, dp, col);
                 break;
         case (TBL_CELL_NUMBER):
-                tbl_number(tp, tbl, dp, col);
+                tbl_number(tp, opts, dp, col);
                 break;
         case (TBL_CELL_DOWN):
                 tbl_char(tp, ASCII_NBRSP, col->width);
                 break;
         default:

@@ -336,20 +313,15 @@
 
 static void
 tbl_vrule(struct termp *tp, const struct tbl_head *hp)
 {
 
-        switch (hp->pos) {
-        case (TBL_HEAD_VERT):
-                term_word(tp, "|");
-                break;
-        case (TBL_HEAD_DVERT):
-                term_word(tp, "||");
-                break;
-        default:
-                break;
-        }
+        tbl_char(tp, ASCII_NBRSP, 1);
+        if (0 < hp->vert)
+                tbl_char(tp, '|', hp->vert);
+        if (2 > hp->vert)
+                tbl_char(tp, ASCII_NBRSP, 2 - hp->vert);
 }
 
 static void
 tbl_char(struct termp *tp, char c, size_t len)
 {

@@ -367,15 +339,23 @@
 
 static void
 tbl_literal(struct termp *tp, const struct tbl_dat *dp, 
                 const struct roffcol *col)
 {
-        size_t           len, padl, padr;
+        struct tbl_head         *hp;
+        size_t                   width, len, padl, padr;
+        int                      spans;
 
         assert(dp->string);
         len = term_strlen(tp, dp->string);
-        padr = col->width > len ? col->width - len : 0;
+
+        hp = dp->layout->head->next;
+        width = col->width;
+        for (spans = dp->spans; spans--; hp = hp->next)
+                width += tp->tbl.cols[hp->ident].width + 3;
+
+        padr = width > len ? width - len : 0;
         padl = 0;
 
         switch (dp->layout->pos) {
         case (TBL_CELL_LONG):
                 padl = term_len(tp, 1);

@@ -399,11 +379,11 @@
         term_word(tp, dp->string);
         tbl_char(tp, ASCII_NBRSP, padr);
 }
 
 static void
-tbl_number(struct termp *tp, const struct tbl *tbl,
+tbl_number(struct termp *tp, const struct tbl_opts *opts,
                 const struct tbl_dat *dp,
                 const struct roffcol *col)
 {
         char            *cp;
         char             buf[2];

@@ -417,16 +397,16 @@
 
         assert(dp->string);
 
         sz = term_strlen(tp, dp->string);
 
-        buf[0] = tbl->decimal;
+        buf[0] = opts->decimal;
         buf[1] = '\0';
 
         psz = term_strlen(tp, buf);
 
-        if (NULL != (cp = strrchr(dp->string, tbl->decimal))) {
+        if (NULL != (cp = strrchr(dp->string, opts->decimal))) {
                 buf[1] = '\0';
                 for (ssz = 0, i = 0; cp != &dp->string[i]; i++) {
                         buf[0] = dp->string[i];
                         ssz += term_strlen(tp, buf);
                 }