--- old/usr/src/cmd/mandoc/tbl_term.c	Fri Jul 25 15:00:16 2014
+++ new/usr/src/cmd/mandoc/tbl_term.c	Fri Jul 25 15:00:16 2014
@@ -1,7 +1,7 @@
-/*	$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
@@ -31,7 +31,7 @@
 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 *);
@@ -38,7 +38,7 @@
 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 *);
@@ -96,16 +96,16 @@
 	/* 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 ? "+" : "|");
 
@@ -126,50 +126,24 @@
 		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.
@@ -185,7 +159,7 @@
 
 	/* 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);
@@ -196,11 +170,15 @@
 	 */
 
 	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;
@@ -222,17 +200,14 @@
 	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)
-			width++;
-		/* Account for trailing blanks. */
-		width++;
-		if (hp->next &&
-		    TBL_HEAD_VERT  != hp->next->pos &&
-		    TBL_HEAD_DVERT != hp->next->pos)
-			width++;
-	}
+
+	/* Account for leading blanks. */
+	if (hp->prev)
+		width += 2 - hp->vert;
+
+	/* Account for trailing blank. */
+	width++;
+
 	return(width);
 }
 
@@ -250,10 +225,11 @@
 	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));
+	}
 }
 
 /*
@@ -268,16 +244,17 @@
 	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)
 {
@@ -323,7 +300,7 @@
 		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);
@@ -338,16 +315,11 @@
 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
@@ -369,11 +341,19 @@
 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) {
@@ -401,7 +381,7 @@
 }
 
 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)
 {
@@ -419,12 +399,12 @@
 
 	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];
