source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Implement automatic line breaking inside individual table cells
@ 2017-06-12 19:05 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2017-06-12 19:05 UTC (permalink / raw)
  To: source

Log Message:
-----------
Implement automatic line breaking
inside individual table cells that contain text blocks.
This cures overlong lines in various Xenocara manuals.

Modified Files:
--------------
    mdocml:
        LICENSE
        Makefile
        configure
        configure.local.example
        mandoc_aux.c
        mandoc_aux.h
        tbl_term.c
        term.c
        term.h
    mdocml/regress/char/unicode:
        input.out_ascii

Added Files:
-----------
    mdocml:
        compat_recallocarray.c
        test-recallocarray.c

Revision Data
-------------
--- /dev/null
+++ compat_recallocarray.c
@@ -0,0 +1,108 @@
+#include "config.h"
+
+#if HAVE_RECALLOCARRAY
+
+int dummy;
+
+#else
+
+/*	$Id: compat_recallocarray.c,v 1.1 2017/06/12 19:05:47 schwarze Exp $ */
+/*	$OpenBSD: malloc.c,v 1.225 2017/05/13 07:11:29 otto Exp $ */
+/*
+ * Copyright (c) 2017 Otto Moerbeek <otto@drijf.net>
+ *
+ * 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.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
+ * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
+ */
+#define MUL_NO_OVERFLOW	((size_t)1 << (sizeof(size_t) * 4))
+
+/*
+ * Even though specified in POSIX, the PAGESIZE and PAGE_SIZE
+ * macros have very poor portability.  Since we only use this
+ * to avoid free() overhead for small shrinking, simply pick
+ * an arbitrary number.
+ */
+#define MALLOC_PAGESIZE         (1UL << 12)
+
+
+void *
+recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size)
+{
+	size_t oldsize, newsize;
+	void *newptr;
+
+	if (ptr == NULL)
+		return calloc(newnmemb, size);
+
+	if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    newnmemb > 0 && SIZE_MAX / newnmemb < size) {
+		errno = ENOMEM;
+		return NULL;
+	}
+	newsize = newnmemb * size;
+
+	if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
+	    oldnmemb > 0 && SIZE_MAX / oldnmemb < size) {
+		errno = EINVAL;
+		return NULL;
+	}
+	oldsize = oldnmemb * size;
+
+	/*
+	 * Don't bother too much if we're shrinking just a bit,
+	 * we do not shrink for series of small steps, oh well.
+	 */
+	if (newsize <= oldsize) {
+		size_t d = oldsize - newsize;
+
+		if (d < oldsize / 2 && d < MALLOC_PAGESIZE) {
+			memset((char *)ptr + newsize, 0, d);
+			return ptr;
+		}
+	}
+
+	newptr = malloc(newsize);
+	if (newptr == NULL)
+		return NULL;
+
+	if (newsize > oldsize) {
+		memcpy(newptr, ptr, oldsize);
+		memset((char *)newptr + oldsize, 0, newsize - oldsize);
+	} else
+		memcpy(newptr, ptr, newsize);
+
+	/*
+	 * At this point, the OpenBSD implementation calls
+	 * explicit_bzero() on the old memory before it is
+	 * freed.  Since explicit_bzero() is hard to implement
+	 * portably and we don't handle confidential data in
+	 * mandoc in the first place, simply free the memory
+	 * without clearing it.
+	 */
+
+	free(ptr);
+
+	return newptr;
+}
+
+#endif /* !HAVE_RECALLOCARRAY */
Index: mandoc_aux.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mandoc_aux.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -Lmandoc_aux.h -Lmandoc_aux.h -u -p -r1.6 -r1.7
--- mandoc_aux.h
+++ mandoc_aux.h
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 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
@@ -22,5 +22,6 @@ void		 *mandoc_calloc(size_t, size_t);
 void		 *mandoc_malloc(size_t);
 void		 *mandoc_realloc(void *, size_t);
 void		 *mandoc_reallocarray(void *, size_t, size_t);
+void		 *mandoc_recallocarray(void *, size_t, size_t, size_t);
 char		 *mandoc_strdup(const char *);
 char		 *mandoc_strndup(const char *, size_t);
Index: LICENSE
===================================================================
RCS file: /home/cvs/mdocml/mdocml/LICENSE,v
retrieving revision 1.15
retrieving revision 1.16
diff -LLICENSE -LLICENSE -u -p -r1.15 -r1.16
--- LICENSE
+++ LICENSE
@@ -13,7 +13,7 @@ Copyright (c) 2016 Ed Maste <emaste@free
 Copyright (c) 2017 Michael Stapelberg <stapelberg@debian.org>
 Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org>
 Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
-Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
+Copyright (c) 2008, 2017 Otto Moerbeek <otto@drijf.net>
 Copyright (c) 2004 Ted Unangst <tedu@openbsd.org>
 Copyright (c) 1994 Christos Zoulas <christos@netbsd.org>
 Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org>
--- /dev/null
+++ test-recallocarray.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+
+int
+main(void)
+{
+	void	*p;
+
+	if ((p = calloc(2, 2)) == NULL)
+		return 1;
+	return !recallocarray(p, 2, 3, 2);
+}
Index: mandoc_aux.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mandoc_aux.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -Lmandoc_aux.c -Lmandoc_aux.c -u -p -r1.9 -r1.10
--- mandoc_aux.c
+++ mandoc_aux.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2014 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
@@ -71,7 +71,6 @@ mandoc_malloc(size_t size)
 void *
 mandoc_realloc(void *ptr, size_t size)
 {
-
 	ptr = realloc(ptr, size);
 	if (ptr == NULL)
 		err((int)MANDOCLEVEL_SYSERR, NULL);
@@ -81,8 +80,16 @@ mandoc_realloc(void *ptr, size_t size)
 void *
 mandoc_reallocarray(void *ptr, size_t num, size_t size)
 {
-
 	ptr = reallocarray(ptr, num, size);
+	if (ptr == NULL)
+		err((int)MANDOCLEVEL_SYSERR, NULL);
+	return ptr;
+}
+
+void *
+mandoc_recallocarray(void *ptr, size_t oldnum, size_t num, size_t size)
+{
+	ptr = recallocarray(ptr, oldnum, num, size);
 	if (ptr == NULL)
 		err((int)MANDOCLEVEL_SYSERR, NULL);
 	return ptr;
Index: term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/term.c,v
retrieving revision 1.268
retrieving revision 1.269
diff -Lterm.c -Lterm.c -u -p -r1.268 -r1.269
--- term.c
+++ term.c
@@ -40,6 +40,18 @@ static	void		 endline(struct termp *);
 
 
 void
+term_setcol(struct termp *p, size_t maxtcol)
+{
+	if (maxtcol > p->maxtcol) {
+		p->tcols = mandoc_recallocarray(p->tcols,
+		    p->maxtcol, maxtcol, sizeof(*p->tcols));
+		p->maxtcol = maxtcol;
+	}
+	p->lasttcol = maxtcol - 1;
+	p->tcol = p->tcols;
+}
+
+void
 term_free(struct termp *p)
 {
 	for (p->tcol = p->tcols; p->tcol < p->tcols + p->maxtcol; p->tcol++)
@@ -116,9 +128,9 @@ term_flushln(struct termp *p)
 	    p->maxrmargin - p->viscol - vbl : 0;
 	vis = vend = 0;
 
-	if (p->lasttcol == 0)
+	if ((p->flags && TERMP_MULTICOL) == 0)
 		p->tcol->col = 0;
-	while (p->tcol->col < p->lastcol) {
+	while (p->tcol->col < p->tcol->lastcol) {
 
 		/*
 		 * Handle literal tab characters: collapse all
@@ -126,7 +138,7 @@ term_flushln(struct termp *p)
 		 */
 
 		ntab = 0;
-		while (p->tcol->col < p->lastcol &&
+		while (p->tcol->col < p->tcol->lastcol &&
 		    p->tcol->buf[p->tcol->col] == '\t') {
 			vend = term_tab_next(vis);
 			vbl += vend - vis;
@@ -143,7 +155,7 @@ term_flushln(struct termp *p)
 		 */
 
 		jhy = 0;
-		for (j = p->tcol->col; j < p->lastcol; j++) {
+		for (j = p->tcol->col; j < p->tcol->lastcol; j++) {
 			if (p->tcol->buf[j] == ' ' || p->tcol->buf[j] == '\t')
 				break;
 
@@ -178,7 +190,7 @@ term_flushln(struct termp *p)
 
 		if (vend > bp && jhy == 0 && vis > 0 &&
 		    (p->flags & TERMP_BRNEVER) == 0) {
-			if (p->lasttcol)
+			if (p->flags & TERMP_MULTICOL)
 				return;
 
 			endline(p);
@@ -206,14 +218,14 @@ term_flushln(struct termp *p)
 		 * Write out the rest of the word.
 		 */
 
-		for ( ; p->tcol->col < p->lastcol; p->tcol->col++) {
+		for ( ; p->tcol->col < p->tcol->lastcol; p->tcol->col++) {
 			if (vend > bp && jhy > 0 && p->tcol->col > jhy)
 				break;
 			if (p->tcol->buf[p->tcol->col] == '\t')
 				break;
 			if (p->tcol->buf[p->tcol->col] == ' ') {
 				j = p->tcol->col;
-				while (p->tcol->col < p->lastcol &&
+				while (p->tcol->col < p->tcol->lastcol &&
 				    p->tcol->buf[p->tcol->col] == ' ')
 					p->tcol->col++;
 				dv = (p->tcol->col - j) * (*p->width)(p, ' ');
@@ -260,10 +272,13 @@ term_flushln(struct termp *p)
 	else
 		vis = 0;
 
-	p->col = p->lastcol = 0;
+	p->col = p->tcol->col = p->tcol->lastcol = 0;
 	p->minbl = p->trailspace;
 	p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE | TERMP_NOPAD);
 
+	if (p->flags & TERMP_MULTICOL)
+		return;
+
 	/* Trailing whitespace is significant in some columns. */
 
 	if (vis && vbl && (TERMP_BRTRSP & p->flags))
@@ -305,7 +320,7 @@ term_newln(struct termp *p)
 {
 
 	p->flags |= TERMP_NOSPACE;
-	if (p->lastcol || p->viscol)
+	if (p->tcol->lastcol || p->viscol)
 		term_flushln(p);
 }
 
@@ -565,12 +580,12 @@ term_word(struct termp *p, const char *w
 				}
 			}
 			/* Trim trailing backspace/blank pair. */
-			if (p->lastcol > 2 &&
-			    (p->tcol->buf[p->lastcol - 1] == ' ' ||
-			     p->tcol->buf[p->lastcol - 1] == '\t'))
-				p->lastcol -= 2;
-			if (p->col > p->lastcol)
-				p->col = p->lastcol;
+			if (p->tcol->lastcol > 2 &&
+			    (p->tcol->buf[p->tcol->lastcol - 1] == ' ' ||
+			     p->tcol->buf[p->tcol->lastcol - 1] == '\t'))
+				p->tcol->lastcol -= 2;
+			if (p->col > p->tcol->lastcol)
+				p->col = p->tcol->lastcol;
 			continue;
 		default:
 			continue;
@@ -613,10 +628,10 @@ bufferc(struct termp *p, char c)
 	}
 	if (p->col + 1 >= p->tcol->maxcols)
 		adjbuf(p->tcol, p->col + 1);
-	if (p->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
+	if (p->tcol->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
 		p->tcol->buf[p->col] = c;
-	if (p->lastcol < ++p->col)
-		p->lastcol = p->col;
+	if (p->tcol->lastcol < ++p->col)
+		p->tcol->lastcol = p->col;
 }
 
 /*
@@ -659,10 +674,10 @@ encode1(struct termp *p, int c)
 			p->tcol->buf[p->col++] = c;
 		p->tcol->buf[p->col++] = '\b';
 	}
-	if (p->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
+	if (p->tcol->lastcol <= p->col || (c != ' ' && c != ASCII_NBRSP))
 		p->tcol->buf[p->col] = c;
-	if (p->lastcol < ++p->col)
-		p->lastcol = p->col;
+	if (p->tcol->lastcol < ++p->col)
+		p->tcol->lastcol = p->col;
 	if (p->flags & TERMP_BACKAFTER) {
 		p->flags |= TERMP_BACKBEFORE;
 		p->flags &= ~TERMP_BACKAFTER;
@@ -688,7 +703,7 @@ encode(struct termp *p, const char *word
 		    isgraph((unsigned char)word[i]))
 			encode1(p, word[i]);
 		else {
-			if (p->lastcol <= p->col ||
+			if (p->tcol->lastcol <= p->col ||
 			    (word[i] != ' ' && word[i] != ASCII_NBRSP))
 				p->tcol->buf[p->col] = word[i];
 			p->col++;
@@ -705,8 +720,8 @@ encode(struct termp *p, const char *word
 			}
 		}
 	}
-	if (p->lastcol < p->col)
-		p->lastcol = p->col;
+	if (p->tcol->lastcol < p->col)
+		p->tcol->lastcol = p->col;
 }
 
 void
Index: configure
===================================================================
RCS file: /home/cvs/mdocml/mdocml/configure,v
retrieving revision 1.62
retrieving revision 1.63
diff -Lconfigure -Lconfigure -u -p -r1.62 -r1.63
--- configure
+++ configure
@@ -73,6 +73,7 @@ HAVE_PATH_MAX=
 HAVE_PLEDGE=
 HAVE_PROGNAME=
 HAVE_REALLOCARRAY=
+HAVE_RECALLOCARRAY=
 HAVE_RECVMSG=
 HAVE_REWB_BSD=
 HAVE_REWB_SYSV=
@@ -229,6 +230,7 @@ runtest pledge		PLEDGE		|| true
 runtest sandbox_init	SANDBOX_INIT	|| true
 runtest progname	PROGNAME	|| true
 runtest reallocarray	REALLOCARRAY	|| true
+runtest recallocarray	RECALLOCARRAY	|| true
 runtest rewb-bsd	REWB_BSD	|| true
 runtest rewb-sysv	REWB_SYSV	|| true
 runtest strcasestr	STRCASESTR	|| true
@@ -348,7 +350,8 @@ cat << __HEREDOC__
 
 __HEREDOC__
 
-[ ${HAVE_GETLINE} -eq 0 -o ${HAVE_REALLOCARRAY} -eq 0 -o \
+[ ${HAVE_GETLINE} -eq 0 -o \
+  ${HAVE_REALLOCARRAY} -eq 0 -o ${HAVE_RECALLOCARRAY} -eq 0 -o \
   ${HAVE_STRLCAT} -eq 0 -o ${HAVE_STRLCPY} -eq 0 ] \
 	&& echo "#include <sys/types.h>"
 [ ${HAVE_VASPRINTF} -eq 0 ] && echo "#include <stdarg.h>"
@@ -383,6 +386,7 @@ cat << __HEREDOC__
 #define HAVE_PLEDGE ${HAVE_PLEDGE}
 #define HAVE_PROGNAME ${HAVE_PROGNAME}
 #define HAVE_REALLOCARRAY ${HAVE_REALLOCARRAY}
+#define HAVE_RECALLOCARRAY ${HAVE_RECALLOCARRAY}
 #define HAVE_REWB_BSD ${HAVE_REWB_BSD}
 #define HAVE_REWB_SYSV ${HAVE_REWB_SYSV}
 #define HAVE_SANDBOX_INIT ${HAVE_SANDBOX_INIT}
@@ -433,6 +437,9 @@ fi
 
 [ ${HAVE_REALLOCARRAY} -eq 0 ] && \
 	echo "extern	void	 *reallocarray(void *, size_t, size_t);"
+
+[ ${HAVE_RECALLOCARRAY} -eq 0 ] && \
+	echo "extern	void	 *recallocarray(void *, size_t, size_t, size_t);"
 
 [ ${HAVE_STRCASESTR} -eq 0 ] && \
 	echo "extern	char	 *strcasestr(const char *, const char *);"
Index: Makefile
===================================================================
RCS file: /home/cvs/mdocml/mdocml/Makefile,v
retrieving revision 1.512
retrieving revision 1.513
diff -LMakefile -LMakefile -u -p -r1.512 -r1.513
--- Makefile
+++ Makefile
@@ -38,6 +38,7 @@ TESTSRCS	 = test-be32toh.c \
 		   test-progname.c \
 		   test-recvmsg.c \
 		   test-reallocarray.c \
+		   test-recallocarray.c \
 		   test-rewb-bsd.c \
 		   test-rewb-sysv.c \
 		   test-sandbox_init.c \
@@ -64,6 +65,7 @@ SRCS		 = att.c \
 		   compat_ohash.c \
 		   compat_progname.c \
 		   compat_reallocarray.c \
+		   compat_recallocarray.c \
 		   compat_strcasestr.c \
 		   compat_stringlist.c \
 		   compat_strlcat.c \
@@ -240,6 +242,7 @@ COMPAT_OBJS	 = compat_err.o \
 		   compat_ohash.o \
 		   compat_progname.o \
 		   compat_reallocarray.o \
+		   compat_recallocarray.o \
 		   compat_strcasestr.o \
 		   compat_strlcat.o \
 		   compat_strlcpy.o \
Index: tbl_term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/tbl_term.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -Ltbl_term.c -Ltbl_term.c -u -p -r1.46 -r1.47
--- tbl_term.c
+++ tbl_term.c
@@ -68,12 +68,13 @@ term_tbl(struct termp *tp, const struct 
 	const struct tbl_cell	*cp;
 	const struct tbl_dat	*dp;
 	static size_t		 offset;
-	size_t			 tsz;
-	int			 ic, horiz, spans, vert;
+	size_t			 coloff, tsz;
+	int			 ic, horiz, spans, vert, more;
+	char			 fc;
 
 	/* Inhibit printing of spaces: we do padding ourselves. */
 
-	tp->flags |= TERMP_NOSPACE | TERMP_NONOSPACE | TERMP_BRNEVER;
+	tp->flags |= TERMP_NOSPACE | TERMP_NONOSPACE;
 
 	/*
 	 * The first time we're invoked for a given table block,
@@ -111,82 +112,181 @@ term_tbl(struct termp *tp, const struct 
 			tbl_hrule(tp, sp, 1);
 	}
 
-	/* Vertical frame at the start of each row. */
+	/* Set up the columns. */
 
-	horiz = sp->pos == TBL_SPAN_HORIZ || sp->pos == TBL_SPAN_DHORIZ;
+	tp->flags |= TERMP_MULTICOL;
+	horiz = 0;
+	switch (sp->pos) {
+	case TBL_SPAN_HORIZ:
+	case TBL_SPAN_DHORIZ:
+		horiz = 1;
+		term_setcol(tp, 1);
+		break;
+	case TBL_SPAN_DATA:
+		term_setcol(tp, sp->opts->cols + 2);
+		coloff = tp->tcol->offset;
+
+		/* Set up a column for a left vertical frame. */
+
+		if (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) ||
+		    sp->opts->lvert)
+			coloff++;
+		tp->tcol->rmargin = coloff;
 
-	if (sp->layout->vert ||
-	    (sp->prev != NULL && sp->prev->layout->vert) ||
-	    sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))
-		term_word(tp, horiz ? "+" : "|");
-	else if (sp->opts->lvert)
-		tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1);
+		/* Set up the data columns. */
 
-	/*
-	 * Now print the actual data itself depending on the span type.
-	 * Match data cells to column numbers.
-	 */
-
-	if (sp->pos == TBL_SPAN_DATA) {
-		cp = sp->layout->first;
 		dp = sp->first;
 		spans = 0;
 		for (ic = 0; ic < sp->opts->cols; ic++) {
-
-			/*
-			 * Remeber whether we need a vertical bar
-			 * after this cell.
-			 */
-
-			vert = cp == NULL ? 0 : cp->vert;
-
-			/*
-			 * Print the data and advance to the next cell.
-			 */
-
 			if (spans == 0) {
-				tbl_data(tp, sp->opts, dp, tp->tbl.cols + ic);
-				if (dp != NULL) {
-					spans = dp->spans;
-					dp = dp->next;
-				}
-			} else
+				tp->tcol++;
+				tp->tcol->offset = coloff;
+			}
+			coloff += tp->tbl.cols[ic].width;
+			tp->tcol->rmargin = coloff;
+			coloff++;
+			if (ic + 1 < sp->opts->cols)
+				coloff += 2;
+			if (spans) {
 				spans--;
-			if (cp != NULL)
-				cp = cp->next;
+				continue;
+			}
+			if (dp == NULL)
+				continue;
+			spans = dp->spans;
+			dp = dp->next;
+		}
+
+		/* Set up a column for a right vertical frame. */
+
+		tp->tcol++;
+		tp->tcol->offset = coloff;
+		if (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX) ||
+		    sp->opts->rvert)
+			coloff++;
+		tp->tcol->rmargin = coloff;
+
+		/* Spans may have reduced the number of columns. */
 
-			/*
-			 * Separate columns, except in the middle
-			 * of spans and after the last cell.
-			 */
+		tp->lasttcol = tp->tcol - tp->tcols;
 
-			if (ic + 1 == sp->opts->cols || spans)
+		/* Fill the buffers for all data columns. */
+
+		tp->tcol = tp->tcols;
+		dp = sp->first;
+		spans = 0;
+		for (ic = 0; ic < sp->opts->cols; ic++) {
+			if (spans) {
+				spans--;
 				continue;
+			}
+			tp->tcol++;
+			tp->col = 0;
+			tbl_data(tp, sp->opts, dp, tp->tbl.cols + ic);
+			if (dp == NULL)
+				continue;
+			spans = dp->spans;
+			dp = dp->next;
+		}
+		break;
+	}
+
+	do {
+		/* Print the vertical frame at the start of each row. */
+
+		tp->tcol = tp->tcols;
+		fc = '\0';
+		if (sp->layout->vert ||
+		    (sp->prev != NULL && sp->prev->layout->vert) ||
+		    sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX))
+			fc = horiz ? '+' : '|';
+		else if (horiz && sp->opts->lvert)
+			fc = '-';
+		if (fc != '\0') {
+			(*tp->advance)(tp, tp->tcols->offset);
+			(*tp->letter)(tp, fc);
+			tp->viscol = tp->tcol->offset + 1;
+		}
 
-			tbl_char(tp, ASCII_NBRSP, 1);
-			if (vert > 0)
-				tbl_char(tp, '|', vert);
-			if (vert < 2)
-				tbl_char(tp, ASCII_NBRSP, 2 - vert);
-		}
-	} else if (horiz)
-		tbl_hrule(tp, sp, 0);
-
-	/* Vertical frame at the end of each row. */
-
-	if (sp->layout->last->vert ||
-	    (sp->prev != NULL && sp->prev->layout->last->vert) ||
-	    (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)))
-		term_word(tp, horiz ? "+" : " |");
-	else if (sp->opts->rvert)
-		tbl_char(tp, horiz ? '-' : ASCII_NBRSP, 1);
-	term_flushln(tp);
+		/* Print the data cells. */
+
+		more = 0;
+		if (horiz) {
+			tbl_hrule(tp, sp, 0);
+			term_flushln(tp);
+		} else {
+			cp = sp->layout->first;
+			dp = sp->first;
+			spans = 0;
+			for (ic = 0; ic < sp->opts->cols; ic++) {
+				if (spans == 0) {
+					tp->tcol++;
+					if (dp != NULL) {
+						spans = dp->spans;
+						dp = dp->next;
+					}
+					if (tp->tcol->col < tp->tcol->lastcol)
+						term_flushln(tp);
+					if (tp->tcol->col < tp->tcol->lastcol)
+						more = 1;
+					if (tp->tcol + 1 ==
+					    tp->tcols + tp->lasttcol)
+						continue;
+				} else
+					spans--;
+
+				/* Vertical frames between data cells. */
+
+				if (cp != NULL) {
+					vert = cp->vert;
+					cp = cp->next;
+				} else
+					vert = 0;
+				if (vert == 0)
+					continue;
+
+				if (tp->tcol->rmargin + 1 > tp->viscol) {
+					(*tp->advance)(tp, tp->tcol->rmargin
+					   + 1 - tp->viscol);
+					tp->viscol = tp->tcol->rmargin + 1;
+				}
+				while (vert--) {
+					(*tp->letter)(tp, '|');
+					tp->viscol++;
+				}
+			}
+		}
+
+		/* Print the vertical frame at the end of each row. */
+
+		fc = '\0';
+		if (sp->layout->last->vert ||
+		    (sp->prev != NULL && sp->prev->layout->last->vert) ||
+		    (sp->opts->opts & (TBL_OPT_BOX | TBL_OPT_DBOX)))
+			fc = horiz ? '+' : '|';
+		else if (horiz && sp->opts->rvert)
+			fc = '-';
+		if (fc != '\0') {
+			if (horiz == 0) {
+				tp->tcol++;
+				(*tp->advance)(tp,
+				    tp->tcol->offset > tp->viscol ?
+				    tp->tcol->offset - tp->viscol : 1);
+			}
+			(*tp->letter)(tp, fc);
+		}
+		(*tp->endline)(tp);
+		tp->viscol = 0;
+	} while (more);
 
 	/*
 	 * If we're the last row, clean up after ourselves: clear the
 	 * existing table configuration and set it to NULL.
 	 */
 
+	term_setcol(tp, 1);
+	tp->flags &= ~TERMP_MULTICOL;
+	tp->tcol->rmargin = tp->maxrmargin;
 	if (sp->next == NULL) {
 		if (sp->opts->opts & (TBL_OPT_DBOX | TBL_OPT_BOX)) {
 			tbl_hrule(tp, sp, 1);
@@ -201,7 +301,7 @@ term_tbl(struct termp *tp, const struct 
 		tp->tbl.cols = NULL;
 		tp->tcol->offset = offset;
 	}
-	tp->flags &= ~(TERMP_NONOSPACE | TERMP_BRNEVER);
+	tp->flags &= ~TERMP_NONOSPACE;
 }
 
 /*
Index: term.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/term.h,v
retrieving revision 1.126
retrieving revision 1.127
diff -Lterm.h -Lterm.h -u -p -r1.126 -r1.127
--- term.h
+++ term.h
@@ -52,6 +52,7 @@ struct	termp_tbl {
 struct	termp_col {
 	int		 *buf;		/* Output buffer. */
 	size_t		  maxcols;	/* Allocated bytes in buf. */
+	size_t		  lastcol;	/* Last byte in buf. */
 	size_t		  col;		/* Byte in buf to be written. */
 	size_t		  rmargin;	/* Current right margin. */
 	size_t		  offset;	/* Current left margin. */
@@ -69,7 +70,6 @@ struct	termp {
 	size_t		  lastrmargin;	/* Right margin before the last ll. */
 	size_t		  maxrmargin;	/* Max right margin. */
 	size_t		  col;		/* Byte position in buf. */
-	size_t		  lastcol;	/* Bytes in buf. */
 	size_t		  viscol;	/* Chars on current line. */
 	size_t		  trailspace;	/* See term_flushln(). */
 	size_t		  minbl;	/* Minimum blanks before next field. */
@@ -98,6 +98,7 @@ struct	termp {
 #define	TERMP_NOBUF	 (1 << 17)	/* Bypass output buffer. */
 #define	TERMP_NEWMC	 (1 << 18)	/* No .mc printed yet. */
 #define	TERMP_ENDMC	 (1 << 19)	/* Next break ends .mc mode. */
+#define	TERMP_MULTICOL	 (1 << 20)	/* Multiple column mode. */
 	enum termtype	  type;		/* Terminal, PS, or PDF. */
 	enum termenc	  enc;		/* Type of encoding. */
 	enum termfont	  fontl;	/* Last font set. */
@@ -128,6 +129,7 @@ void		  roff_term_pre(struct termp *, co
 void		  term_eqn(struct termp *, const struct eqn *);
 void		  term_tbl(struct termp *, const struct tbl_span *);
 void		  term_free(struct termp *);
+void		  term_setcol(struct termp *, size_t);
 void		  term_newln(struct termp *);
 void		  term_vspace(struct termp *);
 void		  term_word(struct termp *, const char *);
Index: configure.local.example
===================================================================
RCS file: /home/cvs/mdocml/mdocml/configure.local.example,v
retrieving revision 1.30
retrieving revision 1.31
diff -Lconfigure.local.example -Lconfigure.local.example -u -p -r1.30 -r1.31
--- configure.local.example
+++ configure.local.example
@@ -292,6 +292,7 @@ HAVE_PATH_MAX=0
 HAVE_PLEDGE=0
 HAVE_PROGNAME=0
 HAVE_REALLOCARRAY=0
+HAVE_RECALLOCARRAY=0
 HAVE_REWB_BSD=0
 HAVE_REWB_SYSV=0
 HAVE_STRCASESTR=0
Index: input.out_ascii
===================================================================
RCS file: /home/cvs/mdocml/mdocml/regress/char/unicode/input.out_ascii,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lregress/char/unicode/input.out_ascii -Lregress/char/unicode/input.out_ascii -u -p -r1.1 -r1.2
--- regress/char/unicode/input.out_ascii
+++ regress/char/unicode/input.out_ascii
@@ -22,7 +22,7 @@ D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
        U+007f   0xc1bf     ??         highest obfuscated ASCII
                 0xc278     ?x         ASCII continuation
        U+0080   0xc280     <80><80>   lowest two-byte
-                0xc2c380   ?`\bA       high continuation
+                0xc2c380   ?`\bA         high continuation
        U+07FF   0xdfbf     <?><?>     highest two-byte
 
    T\bTh\bhr\bre\bee\be-\b-b\bby\byt\bte\be r\bra\ban\bng\bge\be
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-06-12 19:05 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-12 19:05 mdocml: Implement automatic line breaking inside individual table cells schwarze

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).