Implement w layout specifier (minimum column width).
authorschwarze <schwarze@openbsd.org>
Thu, 8 Jun 2017 18:11:15 +0000 (18:11 +0000)
committerschwarze <schwarze@openbsd.org>
Thu, 8 Jun 2017 18:11:15 +0000 (18:11 +0000)
Improve width calculation of text blocks.
Reduces the groff/mandoc diff in Base+Xenocara by about 800 lines.

12 files changed:
regress/usr.bin/mandoc/tbl/mod/Makefile
regress/usr.bin/mandoc/tbl/mod/width.in [new file with mode: 0644]
regress/usr.bin/mandoc/tbl/mod/width.out_ascii [new file with mode: 0644]
share/man/man7/tbl.7
usr.bin/mandoc/mandoc.h
usr.bin/mandoc/out.c
usr.bin/mandoc/out.h
usr.bin/mandoc/tbl.c
usr.bin/mandoc/tbl_data.c
usr.bin/mandoc/tbl_html.c
usr.bin/mandoc/tbl_layout.c
usr.bin/mandoc/tbl_term.c

index ab087b1..df1e8f4 100644 (file)
@@ -1,6 +1,6 @@
-# $OpenBSD: Makefile,v 1.3 2017/05/01 20:53:58 schwarze Exp $
+# $OpenBSD: Makefile,v 1.4 2017/06/08 18:11:15 schwarze Exp $
 
-REGRESS_TARGETS         = badfont expand expand-toowide font misalign
+REGRESS_TARGETS         = badfont expand expand-toowide font misalign width
 LINT_TARGETS    = badfont font
 
 # groff-1.22.3 defects:
diff --git a/regress/usr.bin/mandoc/tbl/mod/width.in b/regress/usr.bin/mandoc/tbl/mod/width.in
new file mode 100644 (file)
index 0000000..702dd19
--- /dev/null
@@ -0,0 +1,14 @@
+.TH TBL-MOD-WIDTH 1 "June 8, 2017" OpenBSD
+.SH NAME
+tbl-mod-width \- width modifier in table layout
+.SH DESCRIPTION
+normal text
+.TS
+box tab(:);
+lw2 | lw(2n) | lw(0.2i) | lw2 .
+a:abcd:T{
+a
+T}:T{
+.SM abcd
+T}
+.TE
diff --git a/regress/usr.bin/mandoc/tbl/mod/width.out_ascii b/regress/usr.bin/mandoc/tbl/mod/width.out_ascii
new file mode 100644 (file)
index 0000000..8ff6bf1
--- /dev/null
@@ -0,0 +1,16 @@
+TBL-MOD-WIDTH(1)            General Commands Manual           TBL-MOD-WIDTH(1)
+
+
+
+N\bNA\bAM\bME\bE
+       tbl-mod-width - width modifier in table layout
+
+D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
+       normal text
+
+       +---+------+----+------+
+       |a  | abcd | a  | abcd |
+       +---+------+----+------+
+
+
+OpenBSD                          June 8, 2017                 TBL-MOD-WIDTH(1)
index e50375e..84fd983 100644 (file)
@@ -1,7 +1,7 @@
-.\"    $OpenBSD: tbl.7,v 1.14 2015/01/29 00:33:14 schwarze Exp $
+.\"    $OpenBSD: tbl.7,v 1.15 2017/06/08 18:11:15 schwarze Exp $
 .\"
 .\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2014, 2015, 2017 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
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: January 29 2015 $
+.Dd $Mdocdate: June 8 2017 $
 .Dt TBL 7
 .Os
 .Sh NAME
@@ -245,7 +245,7 @@ Emit a double-vertical bar instead of data.
 .Pp
 Keys may be followed by a set of modifiers.
 A modifier is either a modifier key or a natural number for specifying
-the minimum width of a column.
+the spacing to the right of the column.
 The following case-insensitive modifier keys are available:
 .Bl -tag -width 2n
 .It Cm b
@@ -284,8 +284,7 @@ Currently ignored.
 Move cell content up by half a table line.
 Currently ignored.
 .It Cm w
-Specify minimum column width.
-Currently ignored.
+Specify the minimum column width.
 .It Cm x
 After determining the width of all other columns, distribute the
 rest of the line length among all columns having the
@@ -300,7 +299,7 @@ minimum width 10, followed by vertical bar, followed by a left-justified
 column of minimum width 10, another vertical bar, then a column using
 bold font justified about the decimal point in numbers:
 .Pp
-.Dl c10 | l10 | nfB
+.Dl cw10 | lw10 | nfB
 .Ss Data
 The data section follows the last layout row.
 By default, cells in a data section are delimited by a tab.
index a0c44e1..d9860bf 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: mandoc.h,v 1.167 2017/06/08 00:21:23 schwarze Exp $ */
+/*     $OpenBSD: mandoc.h,v 1.168 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010-2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -246,9 +246,10 @@ enum       tbl_cellt {
  */
 struct tbl_cell {
        struct tbl_cell  *next;
+       char             *wstr; /* min width represented as a string */
+       size_t            width; /* minimum column width */
+       size_t            spacing; /* to the right of the column */
        int               vert; /* width of subsequent vertical line */
-       enum tbl_cellt    pos;
-       size_t            spacing;
        int               col; /* column number, starting from 0 */
        int               flags;
 #define        TBL_CELL_TALIGN  (1 << 0) /* t, T */
@@ -259,6 +260,7 @@ struct      tbl_cell {
 #define        TBL_CELL_UP      (1 << 5) /* u, U */
 #define        TBL_CELL_WIGN    (1 << 6) /* z, Z */
 #define        TBL_CELL_WMAX    (1 << 7) /* x, X */
+       enum tbl_cellt    pos;
 };
 
 /*
@@ -286,9 +288,10 @@ enum       tbl_datt {
  */
 struct tbl_dat {
        struct tbl_cell  *layout; /* layout cell */
-       int               spans; /* how many spans follow */
        struct tbl_dat   *next;
        char             *string; /* data (NULL if not TBL_DATA_DATA) */
+       int               spans; /* how many spans follow */
+       int               block; /* T{ text block T} */
        enum tbl_datt     pos;
 };
 
index 9cf5c97..e9d6e87 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: out.c,v 1.36 2017/06/08 12:54:40 schwarze Exp $ */
+/*     $OpenBSD: out.c,v 1.37 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
 #include "out.h"
 
 static void    tblcalc_data(struct rofftbl *, struct roffcol *,
-                       const struct tbl_opts *, const struct tbl_dat *);
+                       const struct tbl_opts *, const struct tbl_dat *,
+                       size_t);
 static void    tblcalc_literal(struct rofftbl *, struct roffcol *,
-                       const struct tbl_dat *);
+                       const struct tbl_dat *, size_t);
 static void    tblcalc_number(struct rofftbl *, struct roffcol *,
                        const struct tbl_opts *, const struct tbl_dat *);
 
@@ -104,6 +105,7 @@ void
 tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
        size_t totalwidth)
 {
+       struct roffsu            su;
        const struct tbl_opts   *opts;
        const struct tbl_dat    *dp;
        struct roffcol          *col;
@@ -144,7 +146,16 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
                        col->flags |= dp->layout->flags;
                        if (dp->layout->flags & TBL_CELL_WIGN)
                                continue;
-                       tblcalc_data(tbl, col, opts, dp);
+                       if (dp->layout->wstr != NULL &&
+                           dp->layout->width == 0 &&
+                           a2roffsu(dp->layout->wstr, &su, SCALE_EN)
+                           != NULL)
+                               dp->layout->width =
+                                   (*tbl->sulen)(&su, tbl->arg);
+                       if (col->width < dp->layout->width)
+                               col->width = dp->layout->width;
+                       tblcalc_data(tbl, col, opts, dp, dp->block ?
+                           totalwidth / (sp->opts->cols + 1) : 0);
                }
        }
 
@@ -232,7 +243,7 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
 
 static void
 tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
-               const struct tbl_opts *opts, const struct tbl_dat *dp)
+    const struct tbl_opts *opts, const struct tbl_dat *dp, size_t mw)
 {
        size_t           sz;
 
@@ -249,7 +260,7 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
        case TBL_CELL_CENTRE:
        case TBL_CELL_LEFT:
        case TBL_CELL_RIGHT:
-               tblcalc_literal(tbl, col, dp);
+               tblcalc_literal(tbl, col, dp, mw);
                break;
        case TBL_CELL_NUMBER:
                tblcalc_number(tbl, col, opts, dp);
@@ -263,16 +274,29 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col,
 
 static void
 tblcalc_literal(struct rofftbl *tbl, struct roffcol *col,
-               const struct tbl_dat *dp)
+    const struct tbl_dat *dp, size_t mw)
 {
-       size_t           sz;
-       const char      *str;
-
-       str = dp->string ? dp->string : "";
-       sz = (*tbl->slen)(str, tbl->arg);
-
-       if (col->width < sz)
-               col->width = sz;
+       const char      *str;   /* Beginning of the first line. */
+       const char      *beg;   /* Beginning of the current line. */
+       char            *end;   /* End of the current line. */
+       size_t           sz;    /* Length of the current line. */
+
+       if (dp->string == NULL || *dp->string == '\0')
+               return;
+       str = mw ? mandoc_strdup(dp->string) : dp->string;
+       for (beg = str; beg != NULL && *beg != '\0'; beg = end) {
+               end = mw ? strchr(beg, ' ') : NULL;
+               if (end != NULL) {
+                       *end++ = '\0';
+                       while (*end == ' ')
+                               end++;
+               }
+               sz = (*tbl->slen)(beg, tbl->arg);
+               if (col->width < sz)
+                       col->width = sz;
+       }
+       if (mw)
+               free((void *)str);
 }
 
 static void
index 4856dfb..7e93f1c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: out.h,v 1.19 2017/06/08 12:54:40 schwarze Exp $ */
+/*     $OpenBSD: out.h,v 1.20 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014, 2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -41,14 +41,16 @@ struct      roffsu {
        double            scale;
 };
 
+typedef        size_t  (*tbl_sulen)(const struct roffsu *, void *);
 typedef        size_t  (*tbl_strlen)(const char *, void *);
 typedef        size_t  (*tbl_len)(size_t, void *);
 
 struct rofftbl {
+       tbl_sulen        sulen; /* calculate scaling unit length */
        tbl_strlen       slen; /* calculate string length */
        tbl_len          len; /* produce width of empty space */
        struct roffcol  *cols; /* master column specifiers */
-       void            *arg; /* passed to slen and len */
+       void            *arg; /* passed to sulen, slen, and len */
 };
 
 #define        SCALE_VS_INIT(p, v) \
index 0e638a4..63e91b7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tbl.c,v 1.21 2015/10/06 18:30:44 schwarze Exp $ */
+/*     $OpenBSD: tbl.c,v 1.22 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
@@ -112,6 +112,7 @@ tbl_free(struct tbl_node *tbl)
                while (rp->first != NULL) {
                        cp = rp->first;
                        rp->first = cp->next;
+                       free(cp->wstr);
                        free(cp);
                }
                free(rp);
index 479d892..5d87e23 100644 (file)
@@ -1,7 +1,7 @@
-/*     $OpenBSD: tbl_data.c,v 1.28 2015/10/06 18:30:44 schwarze Exp $ */
+/*     $OpenBSD: tbl_data.c,v 1.29 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2015, 2017 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
@@ -142,6 +142,7 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos)
        }
 
        dat->pos = TBL_DATA_DATA;
+       dat->block = 1;
 
        if (dat->string != NULL) {
                sz = strlen(p + pos) + strlen(dat->string) + 2;
index 3851549..c839d51 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tbl_html.c,v 1.15 2017/02/05 18:13:28 schwarze Exp $ */
+/*     $OpenBSD: tbl_html.c,v 1.16 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
 static void     html_tblopen(struct html *, const struct tbl_span *);
 static size_t   html_tbl_len(size_t, void *);
 static size_t   html_tbl_strlen(const char *, void *);
+static size_t   html_tbl_sulen(const struct roffsu *, void *);
 
 
 static size_t
 html_tbl_len(size_t sz, void *arg)
 {
-
        return sz;
 }
 
 static size_t
 html_tbl_strlen(const char *p, void *arg)
 {
-
        return strlen(p);
 }
 
+static size_t
+html_tbl_sulen(const struct roffsu *su, void *arg)
+{
+       switch (su->unit) {
+       case SCALE_FS:  /* 2^16 basic units */
+               return su->scale * 65536.0 / 24.0;
+       case SCALE_IN:  /* 10 characters per inch */
+               return su->scale * 10.0;
+       case SCALE_CM:  /* 2.54 cm per inch */
+               return su->scale * 10.0 / 2.54;
+       case SCALE_PC:  /* 6 pica per inch */
+       case SCALE_VS:
+               return su->scale * 10.0 / 6.0;
+       case SCALE_EN:
+       case SCALE_EM:
+               return su->scale;
+       case SCALE_PT:  /* 12 points per pica */
+               return su->scale * 10.0 / 6.0 / 12.0;
+       case SCALE_BU:  /* 24 basic units per character */
+               return su->scale / 24.0;
+       case SCALE_MM:  /* 1/1000 inch */
+               return su->scale / 100.0;
+       default:
+               abort();
+       }
+}
+
 static void
 html_tblopen(struct html *h, const struct tbl_span *sp)
 {
@@ -54,6 +80,7 @@ html_tblopen(struct html *h, const struct tbl_span *sp)
        if (h->tbl.cols == NULL) {
                h->tbl.len = html_tbl_len;
                h->tbl.slen = html_tbl_strlen;
+               h->tbl.sulen = html_tbl_sulen;
                tblcalc(&h->tbl, sp, 0);
        }
 
index 57f21e6..b3b1cfa 100644 (file)
@@ -1,7 +1,7 @@
-/*     $OpenBSD: tbl_layout.c,v 1.28 2015/10/12 00:07:27 schwarze Exp $ */
+/*     $OpenBSD: tbl_layout.c,v 1.29 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012, 2014, 2015, 2017 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
@@ -60,6 +60,7 @@ mods(struct tbl_node *tbl, struct tbl_cell *cp,
                int ln, const char *p, int *pos)
 {
        char            *endptr;
+       size_t           sz;
 
 mod:
        while (p[*pos] == ' ' || p[*pos] == '\t')
@@ -125,7 +126,22 @@ mod:
        case 'u':
                cp->flags |= TBL_CELL_UP;
                goto mod;
-       case 'w':  /* XXX for now, ignore minimal column width */
+       case 'w':
+               sz = 0;
+               if (p[*pos] == '(') {
+                       (*pos)++;
+                       while (p[*pos + sz] != '\0' && p[*pos + sz] != ')')
+                               sz++;
+               } else
+                       while (isdigit((unsigned char)p[*pos + sz]))
+                               sz++;
+               if (sz) {
+                       free(cp->wstr);
+                       cp->wstr = mandoc_strndup(p + *pos, sz);
+                       *pos += sz;
+                       if (p[*pos] == ')')
+                               (*pos)++;
+               }
                goto mod;
        case 'x':
                cp->flags |= TBL_CELL_WMAX;
index 7e45904..1bb94b7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: tbl_term.c,v 1.33 2017/06/07 17:38:08 schwarze Exp $ */
+/*     $OpenBSD: tbl_term.c,v 1.34 2017/06/08 18:11:15 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011,2012,2014,2015,2017 Ingo Schwarze <schwarze@openbsd.org>
@@ -28,6 +28,7 @@
 
 static size_t  term_tbl_len(size_t, void *);
 static size_t  term_tbl_strlen(const char *, void *);
+static size_t  term_tbl_sulen(const struct roffsu *, void *);
 static void    tbl_char(struct termp *, char, size_t);
 static void    tbl_data(struct termp *, const struct tbl_opts *,
                        const struct tbl_dat *,
@@ -42,16 +43,20 @@ static      void    tbl_word(struct termp *, const struct tbl_dat *);
 
 
 static size_t
-term_tbl_strlen(const char *p, void *arg)
+term_tbl_sulen(const struct roffsu *su, void *arg)
 {
+       return term_hspan((const struct termp *)arg, su) / 24;
+}
 
+static size_t
+term_tbl_strlen(const char *p, void *arg)
+{
        return term_strlen((const struct termp *)arg, p);
 }
 
 static size_t
 term_tbl_len(size_t sz, void *arg)
 {
-
        return term_len((const struct termp *)arg, sz);
 }
 
@@ -76,6 +81,7 @@ term_tbl(struct termp *tp, const struct tbl_span *sp)
        if (tp->tbl.cols == NULL) {
                tp->tbl.len = term_tbl_len;
                tp->tbl.slen = term_tbl_strlen;
+               tp->tbl.sulen = term_tbl_sulen;
                tp->tbl.arg = tp;
 
                tblcalc(&tp->tbl, sp, tp->tcol->rmargin - tp->tcol->offset);