source@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: schwarze@mdocml.bsd.lv
To: source@mdocml.bsd.lv
Subject: mdocml: Rudimentary implementation of the e, x, and z table layout
Date: Mon, 13 Oct 2014 22:16:06 -0400 (EDT)	[thread overview]
Message-ID: <201410140216.s9E2G6ku016199@krisdoz.my.domain> (raw)

Log Message:
-----------
Rudimentary implementation of the e, x, and z table layout modifiers
to equalize, maximize, and ignore the width of columns.
Does not yet take vertical rulers into account,
and does not do line breaks within table cells.
Considerably improves the lftp(1) manual; issue noticed by sthen@.

Modified Files:
--------------
    mdocml:
        mandoc.h
        out.c
        out.h
        tbl.7
        tbl_html.c
        tbl_layout.c
        tbl_term.c

Revision Data
-------------
Index: tbl.7
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/tbl.7,v
retrieving revision 1.19
retrieving revision 1.20
diff -Ltbl.7 -Ltbl.7 -u -p -r1.19 -r1.20
--- tbl.7
+++ tbl.7
@@ -248,6 +248,11 @@ The following case-insensitive modifier 
 .Bl -tag -width 2n
 .It Cm b
 Use a bold font for the contents of this column.
+.It Cm e
+Make this column wider to match the maximum width
+of any other column also having the
+.Cm e
+modifier.
 .It Cm f
 The next character selects the font to use for this column.
 See the
@@ -255,16 +260,21 @@ See the
 manual for supported one-character font names.
 .It Cm i
 Use an italic font for the contents of this column.
+.It Cm x
+After determining the width of all other columns, distribute the
+rest of the line length among all columns having the
+.Cm x
+modifier.
+.It Cm z
+Do not use this cell for determining the width of this column.
 .El
 .Pp
 The modifiers
 .Cm d ,
-.Cm e ,
-.Cm r ,
 .Cm t ,
 .Cm u ,
 and
-.Cm z
+.Cm w
 are ignored by
 .Xr mandoc 1 .
 .Pp
Index: out.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/out.c,v
retrieving revision 1.51
retrieving revision 1.52
diff -Lout.c -Lout.c -u -p -r1.51 -r1.52
--- out.c
+++ out.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2014 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
@@ -139,11 +139,14 @@ a2roffsu(const char *src, struct roffsu 
  * used for the actual width calculations.
  */
 void
-tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
+tblcalc(struct rofftbl *tbl, const struct tbl_span *sp,
+	size_t totalwidth)
 {
 	const struct tbl_dat	*dp;
 	struct roffcol		*col;
+	size_t			 ewidth, xwidth;
 	int			 spans;
+	int			 icol, maxcol, necol, nxcol;
 
 	/*
 	 * Allocate the master column specifiers.  These will hold the
@@ -155,7 +158,7 @@ tblcalc(struct rofftbl *tbl, const struc
 	tbl->cols = mandoc_calloc((size_t)sp->opts->cols,
 	    sizeof(struct roffcol));
 
-	for ( ; sp; sp = sp->next) {
+	for (maxcol = 0; sp; sp = sp->next) {
 		if (TBL_SPAN_DATA != sp->pos)
 			continue;
 		spans = 1;
@@ -170,9 +173,70 @@ tblcalc(struct rofftbl *tbl, const struc
 			spans = dp->spans;
 			if (1 < spans)
 				continue;
-			assert(dp->layout);
-			col = &tbl->cols[dp->layout->head->ident];
+			icol = dp->layout->head->ident;
+			if (maxcol < icol)
+				maxcol = icol;
+			col = tbl->cols + icol;
+			col->flags |= dp->layout->flags;
+			if (dp->layout->flags & TBL_CELL_WIGN)
+				continue;
 			tblcalc_data(tbl, col, sp->opts, dp);
+		}
+	}
+
+	/*
+	 * Count columns to equalize and columns to maximize.
+	 * Find maximum width of the columns to equalize.
+	 * Find total width of the columns *not* to maximize.
+	 */
+
+	necol = nxcol = 0;
+	ewidth = xwidth = 0;
+	for (icol = 0; icol <= maxcol; icol++) {
+		col = tbl->cols + icol;
+		if (col->flags & TBL_CELL_EQUAL) {
+			necol++;
+			if (ewidth < col->width)
+				ewidth = col->width;
+		}
+		if (col->flags & TBL_CELL_WMAX)
+			nxcol++;
+		else
+			xwidth += col->width;
+	}
+
+	/*
+	 * Equalize columns, if requested for any of them.
+	 * Update total width of the columns not to maximize.
+	 */
+
+	if (necol) {
+		for (icol = 0; icol <= maxcol; icol++) {
+			col = tbl->cols + icol;
+			if ( ! (col->flags & TBL_CELL_EQUAL))
+				continue;
+			if (col->width == ewidth)
+				continue;
+			if (nxcol && totalwidth)
+				xwidth += ewidth - col->width;
+			col->width = ewidth;
+		}
+	}
+
+	/*
+	 * If there are any columns to maximize, find the total
+	 * available width, deducting 3n margins between columns.
+	 * Distribute the available width evenly.
+	 */
+
+	if (nxcol && totalwidth) {
+		xwidth = totalwidth - 3*maxcol - xwidth;
+		for (icol = 0; icol <= maxcol; icol++) {
+			col = tbl->cols + icol;
+			if ( ! (col->flags & TBL_CELL_WMAX))
+				continue;
+			col->width = xwidth / nxcol--;
+			xwidth -= col->width;
 		}
 	}
 }
Index: out.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/out.h,v
retrieving revision 1.23
retrieving revision 1.24
diff -Lout.h -Lout.h -u -p -r1.23 -r1.24
--- out.h
+++ out.h
@@ -34,6 +34,7 @@ enum	roffscale {
 struct	roffcol {
 	size_t		 width; /* width of cell */
 	size_t		 decimal; /* decimal position in cell */
+	int		 flags; /* layout flags, see tbl_cell */
 };
 
 struct	roffsu {
@@ -64,7 +65,8 @@ __BEGIN_DECLS
 	while (/* CONSTCOND */ 0)
 
 int		  a2roffsu(const char *, struct roffsu *, enum roffscale);
-void		  tblcalc(struct rofftbl *tbl, const struct tbl_span *);
+void		  tblcalc(struct rofftbl *tbl,
+			const struct tbl_span *, size_t);
 
 __END_DECLS
 
Index: tbl_term.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/tbl_term.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -Ltbl_term.c -Ltbl_term.c -u -p -r1.29 -r1.30
--- tbl_term.c
+++ tbl_term.c
@@ -91,7 +91,7 @@ term_tbl(struct termp *tp, const struct 
 		tp->tbl.slen = term_tbl_strlen;
 		tp->tbl.arg = tp;
 
-		tblcalc(&tp->tbl, sp);
+		tblcalc(&tp->tbl, sp, rmargin - tp->offset);
 	}
 
 	/* Horizontal frame at the start of boxed tables. */
Index: tbl_layout.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/tbl_layout.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -Ltbl_layout.c -Ltbl_layout.c -u -p -r1.28 -r1.29
--- tbl_layout.c
+++ tbl_layout.c
@@ -168,6 +168,9 @@ mod:
 		goto mod;
 	case 'w':  /* XXX for now, ignore minimal column width */
 		goto mod;
+	case 'x':
+		cp->flags |= TBL_CELL_WMAX;
+		goto mod;
 	case 'f':
 		break;
 	case 'r':
Index: mandoc.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.h,v
retrieving revision 1.162
retrieving revision 1.163
diff -Lmandoc.h -Lmandoc.h -u -p -r1.162 -r1.163
--- mandoc.h
+++ mandoc.h
@@ -246,6 +246,7 @@ struct	tbl_cell {
 #define	TBL_CELL_EQUAL	 (1 << 4) /* e, E */
 #define	TBL_CELL_UP	 (1 << 5) /* u, U */
 #define	TBL_CELL_WIGN	 (1 << 6) /* z, Z */
+#define	TBL_CELL_WMAX	 (1 << 7) /* x, X */
 	struct tbl_head	 *head;
 };
 
Index: tbl_html.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/tbl_html.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -Ltbl_html.c -Ltbl_html.c -u -p -r1.12 -r1.13
--- tbl_html.c
+++ tbl_html.c
@@ -57,7 +57,7 @@ html_tblopen(struct html *h, const struc
 	if (TBL_SPAN_FIRST & sp->flags) {
 		h->tbl.len = html_tbl_len;
 		h->tbl.slen = html_tbl_strlen;
-		tblcalc(&h->tbl, sp);
+		tblcalc(&h->tbl, sp, 0);
 	}
 
 	assert(NULL == h->tblt);
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

                 reply	other threads:[~2014-10-14  2:16 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201410140216.s9E2G6ku016199@krisdoz.my.domain \
    --to=schwarze@mdocml.bsd.lv \
    --cc=source@mdocml.bsd.lv \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).