summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mandoc.h9
-rw-r--r--out.c52
-rw-r--r--out.h4
-rw-r--r--regress/tbl/mod/Makefile2
-rw-r--r--regress/tbl/mod/width.in14
-rw-r--r--regress/tbl/mod/width.out_ascii16
-rw-r--r--tbl.79
-rw-r--r--tbl.c1
-rw-r--r--tbl_data.c3
-rw-r--r--tbl_html.c31
-rw-r--r--tbl_layout.c20
-rw-r--r--tbl_term.c10
12 files changed, 140 insertions, 31 deletions
diff --git a/mandoc.h b/mandoc.h
index 512dbf1e..b4555398 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -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;
};
diff --git a/out.c b/out.c
index 8b912c98..6e517373 100644
--- a/out.c
+++ b/out.c
@@ -29,9 +29,10 @@
#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 *);
@@ -106,6 +107,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;
@@ -146,7 +148,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);
}
}
@@ -234,7 +245,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;
@@ -251,7 +262,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);
@@ -265,16 +276,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
diff --git a/out.h b/out.h
index f7aeea38..1db24ff0 100644
--- a/out.h
+++ b/out.h
@@ -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) \
diff --git a/regress/tbl/mod/Makefile b/regress/tbl/mod/Makefile
index 04eec17e..09f98bf1 100644
--- a/regress/tbl/mod/Makefile
+++ b/regress/tbl/mod/Makefile
@@ -1,6 +1,6 @@
# $OpenBSD: Makefile,v 1.2 2015/02/10 11:02:19 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/tbl/mod/width.in b/regress/tbl/mod/width.in
new file mode 100644
index 00000000..702dd19e
--- /dev/null
+++ b/regress/tbl/mod/width.in
@@ -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/tbl/mod/width.out_ascii b/regress/tbl/mod/width.out_ascii
new file mode 100644
index 00000000..8ff6bf19
--- /dev/null
+++ b/regress/tbl/mod/width.out_ascii
@@ -0,0 +1,16 @@
+TBL-MOD-WIDTH(1) General Commands Manual TBL-MOD-WIDTH(1)
+
+
+
+NNAAMMEE
+ tbl-mod-width - width modifier in table layout
+
+DDEESSCCRRIIPPTTIIOONN
+ normal text
+
+ +---+------+----+------+
+ |a | abcd | a | abcd |
+ +---+------+----+------+
+
+
+OpenBSD June 8, 2017 TBL-MOD-WIDTH(1)
diff --git a/tbl.7 b/tbl.7
index 23bd01b3..0ba44182 100644
--- a/tbl.7
+++ b/tbl.7
@@ -1,7 +1,7 @@
.\" $Id$
.\"
.\" 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
@@ -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.
diff --git a/tbl.c b/tbl.c
index b7205bfa..83f77348 100644
--- a/tbl.c
+++ b/tbl.c
@@ -114,6 +114,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);
diff --git a/tbl_data.c b/tbl_data.c
index bebf9278..19255b98 100644
--- a/tbl_data.c
+++ b/tbl_data.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* 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
@@ -144,6 +144,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;
diff --git a/tbl_html.c b/tbl_html.c
index b230c9c3..16474440 100644
--- a/tbl_html.c
+++ b/tbl_html.c
@@ -31,22 +31,48 @@
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)
{
@@ -56,6 +82,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);
}
diff --git a/tbl_layout.c b/tbl_layout.c
index 87e74a2b..946fa013 100644
--- a/tbl_layout.c
+++ b/tbl_layout.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* 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
@@ -62,6 +62,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')
@@ -127,7 +128,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;
diff --git a/tbl_term.c b/tbl_term.c
index c6e58b4c..351b262a 100644
--- a/tbl_term.c
+++ b/tbl_term.c
@@ -30,6 +30,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 *,
@@ -44,16 +45,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);
}
@@ -78,6 +83,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);