discuss@mandoc.bsd.lv
 help / color / mirror / Atom feed
From: Ingo Schwarze <schwarze@usta.de>
To: Pali Rohar <pali.rohar@gmail.com>
Cc: discuss@mandoc.bsd.lv
Subject: Re: Broken tables in HTML output
Date: Sun, 25 Nov 2018 20:34:34 +0100	[thread overview]
Message-ID: <20181125193434.GC45828@athene.usta.de> (raw)
In-Reply-To: <20180716152919.GB85992@athene.usta.de>

Hi Pali,

Ingo Schwarze wrote on Mon, Jul 16, 2018 at 05:29:19PM +0200:
> Pali Rohar wrote on Mon, Jul 16, 2018 at 01:03:35PM +0200:

>> cell spanning is broken,

> More precisely, it is not implemented.  I added an entry to the TODO
> file, priority is moderate:
> 
>  - implement cell spanning in HTML output
>    pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
>    loc *  exist *  algo **  size **  imp **

Implemented in the commit below.

Yours,
  Ingo


Log Message:
-----------
In tbl(7) -T html output, 
span cells horizontally and vertically as requested by the layout.  
Does not handle spans requested in the data section yet.

To be able to do this, record the number of rows spanned 
in the first data cell (struct tbl_dat) of a vertical span.

Missing feature reported by Pali dot Rohar at gmail dot com.

Modified Files:
--------------
    mandoc:
        TODO
        mandoc.h
        out.c
        tbl_data.c
        tbl_html.c
        tbl_term.c
        tree.c

Revision Data
-------------
Index: tbl_term.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/tbl_term.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -Ltbl_term.c -Ltbl_term.c -u -p -r1.60 -r1.61
--- tbl_term.c
+++ tbl_term.c
@@ -77,7 +77,7 @@ term_tbl(struct termp *tp, const struct 
 	const struct tbl_dat	*dp;
 	static size_t		 offset;
 	size_t			 coloff, tsz;
-	int			 ic, horiz, spans, vert, more;
+	int			 ic, horiz, hspans, vert, more;
 	char			 fc;
 
 	/* Inhibit printing of spaces: we do padding ourselves. */
@@ -157,9 +157,9 @@ term_tbl(struct termp *tp, const struct 
 		/* Set up the data columns. */
 
 		dp = sp->first;
-		spans = 0;
+		hspans = 0;
 		for (ic = 0; ic < sp->opts->cols; ic++) {
-			if (spans == 0) {
+			if (hspans == 0) {
 				tp->tcol++;
 				tp->tcol->offset = coloff;
 			}
@@ -167,13 +167,13 @@ term_tbl(struct termp *tp, const struct 
 			tp->tcol->rmargin = coloff;
 			if (ic + 1 < sp->opts->cols)
 				coloff += tp->tbl.cols[ic].spacing;
-			if (spans) {
-				spans--;
+			if (hspans) {
+				hspans--;
 				continue;
 			}
 			if (dp == NULL)
 				continue;
-			spans = dp->spans;
+			hspans = dp->hspans;
 			if (ic || sp->layout->first->pos != TBL_CELL_SPAN)
 				dp = dp->next;
 		}
@@ -193,14 +193,14 @@ term_tbl(struct termp *tp, const struct 
 		tp->tcol = tp->tcols;
 		cp = cpn = sp->layout->first;
 		dp = sp->first;
-		spans = 0;
+		hspans = 0;
 		for (ic = 0; ic < sp->opts->cols; ic++) {
 			if (cpn != NULL) {
 				cp = cpn;
 				cpn = cpn->next;
 			}
-			if (spans) {
-				spans--;
+			if (hspans) {
+				hspans--;
 				continue;
 			}
 			tp->tcol++;
@@ -208,7 +208,7 @@ term_tbl(struct termp *tp, const struct 
 			tbl_data(tp, sp->opts, cp, dp, tp->tbl.cols + ic);
 			if (dp == NULL)
 				continue;
-			spans = dp->spans;
+			hspans = dp->hspans;
 			if (cp->pos != TBL_CELL_SPAN)
 				dp = dp->next;
 		}
@@ -249,7 +249,7 @@ term_tbl(struct termp *tp, const struct 
 			cpp = sp->prev == NULL ? NULL :
 			    sp->prev->layout->first;
 			dp = sp->first;
-			spans = 0;
+			hspans = 0;
 			for (ic = 0; ic < sp->opts->cols; ic++) {
 
 				/*
@@ -304,12 +304,12 @@ term_tbl(struct termp *tp, const struct 
 				 * and advance to next data cell.
 				 */
 
-				if (spans) {
-					spans--;
+				if (hspans) {
+					hspans--;
 					continue;
 				}
 				if (dp != NULL) {
-					spans = dp->spans;
+					hspans = dp->hspans;
 					if (ic || sp->layout->first->pos
 					    != TBL_CELL_SPAN)
 						dp = dp->next;
@@ -592,14 +592,14 @@ tbl_literal(struct termp *tp, const stru
 		const struct roffcol *col)
 {
 	size_t		 len, padl, padr, width;
-	int		 ic, spans;
+	int		 ic, hspans;
 
 	assert(dp->string);
 	len = term_strlen(tp, dp->string);
 	width = col->width;
 	ic = dp->layout->col;
-	spans = dp->spans;
-	while (spans--)
+	hspans = dp->hspans;
+	while (hspans--)
 		width += tp->tbl.cols[++ic].width + 3;
 
 	padr = width > len ? width - len : 0;
Index: tbl_html.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/tbl_html.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -Ltbl_html.c -Ltbl_html.c -u -p -r1.25 -r1.26
--- tbl_html.c
+++ tbl_html.c
@@ -101,10 +101,10 @@ print_tblclose(struct html *h)
 void
 print_tbl(struct html *h, const struct tbl_span *sp)
 {
-	const struct tbl_dat *dp;
-	struct tag	*tt;
-	const char	*halign, *valign;
-	int		 ic;
+	const struct tbl_dat	*dp;
+	struct tag		*tt;
+	const char		*hspans, *vspans, *halign, *valign;
+	char			 hbuf[4], vbuf[4];
 
 	/* Inhibit printing of spaces: we do padding ourselves. */
 
@@ -124,13 +124,31 @@ print_tbl(struct html *h, const struct t
 		print_otag(h, TAG_TD, "?", "colspan", "0");
 		break;
 	default:
-		dp = sp->first;
-		for (ic = 0; ic < sp->opts->cols; ic++) {
+		for (dp = sp->first; dp != NULL; dp = dp->next) {
 			print_stagq(h, tt);
-			if (dp == NULL || dp->layout->col > ic) {
-				print_otag(h, TAG_TD, "");
+			switch (dp->layout->pos) {
+			case TBL_CELL_SPAN:
+			case TBL_CELL_DOWN:
 				continue;
+			default:
+				break;
 			}
+
+			/* Determine the attribute values. */
+
+			if (dp->hspans > 0) {
+				(void)snprintf(hbuf, sizeof(hbuf),
+				    "%d", dp->hspans + 1);
+				hspans = hbuf;
+			} else
+				hspans = NULL;
+			if (dp->vspans > 0) {
+				(void)snprintf(vbuf, sizeof(vbuf),
+				    "%d", dp->vspans + 1);
+				vspans = vbuf;
+			} else
+				vspans = NULL;
+
 			switch (dp->layout->pos) {
 			case TBL_CELL_CENTRE:
 				halign = "center";
@@ -149,22 +167,27 @@ print_tbl(struct html *h, const struct t
 				valign = "bottom";
 			else
 				valign = NULL;
+
+			/* Print the element and the attributes. */
+
 			if (halign == NULL && valign == NULL)
-				print_otag(h, TAG_TD, "");
+				print_otag(h, TAG_TD, "??",
+				    "colspan", hspans, "rowspan", vspans);
 			else if (halign == NULL)
-				print_otag(h, TAG_TD, "s",
+				print_otag(h, TAG_TD, "??s",
+				    "colspan", hspans, "rowspan", vspans,
 				    "vertical-align", valign);
 			else if (valign == NULL)
-				print_otag(h, TAG_TD, "s",
+				print_otag(h, TAG_TD, "??s",
+				    "colspan", hspans, "rowspan", vspans,
 				    "text-align", halign);
 			else
-				print_otag(h, TAG_TD, "ss",
+				print_otag(h, TAG_TD, "??ss",
+				    "colspan", hspans, "rowspan", vspans,
 				    "vertical-align", valign,
 				    "text-align", halign);
-			if (dp->layout->pos != TBL_CELL_DOWN)
-				if (dp->string != NULL)
-					print_text(h, dp->string);
-			dp = dp->next;
+			if (dp->string != NULL)
+				print_text(h, dp->string);
 		}
 		break;
 	}
Index: tbl_data.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/tbl_data.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -Ltbl_data.c -Ltbl_data.c -u -p -r1.45 -r1.46
--- tbl_data.c
+++ tbl_data.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2011, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2011, 2015, 2017, 2018 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
@@ -40,8 +40,9 @@ static void
 getdata(struct tbl_node *tbl, struct tbl_span *dp,
 		int ln, const char *p, int *pos)
 {
-	struct tbl_dat	*dat;
+	struct tbl_dat	*dat, *pdat;
 	struct tbl_cell	*cp;
+	struct tbl_span	*pdp;
 	int		 sv;
 
 	/* Advance to the next layout cell, skipping spanners. */
@@ -73,15 +74,51 @@ getdata(struct tbl_node *tbl, struct tbl
 		}
 	}
 
-	dat = mandoc_calloc(1, sizeof(*dat));
+	dat = mandoc_malloc(sizeof(*dat));
 	dat->layout = cp;
+	dat->next = NULL;
+	dat->string = NULL;
+	dat->hspans = 0;
+	dat->vspans = 0;
+	dat->block = 0;
 	dat->pos = TBL_DATA_NONE;
-	dat->spans = 0;
+
+	/*
+	 * Increment the number of vertical spans in a data cell above,
+	 * if this cell vertically extends one or more cells above.
+	 * The iteration must be done over data rows,
+	 * not over layout rows, because one layout row
+	 * can be reused for more than one data row.
+	 */
+
+	if (cp->pos == TBL_CELL_DOWN) {
+		pdp = dp;
+		while ((pdp = pdp->prev) != NULL) {
+			pdat = pdp->first;
+			while (pdat != NULL &&
+			    pdat->layout->col < dat->layout->col)
+				pdat = pdat->next;
+			if (pdat == NULL)
+				break;
+			if (pdat->layout->pos != TBL_CELL_DOWN) {
+				pdat->vspans++;
+				break;
+			}
+		}
+	}
+
+	/*
+	 * Count the number of horizontal spans to the right of this cell.
+	 * This is purely a matter of the layout, independent of the data.
+	 */
+
 	for (cp = cp->next; cp != NULL; cp = cp->next)
 		if (cp->pos == TBL_CELL_SPAN)
-			dat->spans++;
+			dat->hspans++;
 		else
 			break;
+
+	/* Append the new data cell to the data row. */
 
 	if (dp->last == NULL)
 		dp->first = dat;
Index: out.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/out.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -Lout.c -Lout.c -u -p -r1.73 -r1.74
--- out.c
+++ out.c
@@ -112,7 +112,7 @@ tblcalc(struct rofftbl *tbl, const struc
 	const struct tbl_dat	*dp;
 	struct roffcol		*col;
 	size_t			 ewidth, xwidth;
-	int			 spans;
+	int			 hspans;
 	int			 icol, maxcol, necol, nxcol, quirkcol;
 
 	/*
@@ -129,17 +129,17 @@ tblcalc(struct rofftbl *tbl, const struc
 	for (maxcol = -1; sp; sp = sp->next) {
 		if (TBL_SPAN_DATA != sp->pos)
 			continue;
-		spans = 1;
+		hspans = 1;
 		/*
 		 * Account for the data cells in the layout, matching it
 		 * to data cells in the data section.
 		 */
 		for (dp = sp->first; dp; dp = dp->next) {
 			/* Do not used spanned cells in the calculation. */
-			if (0 < --spans)
+			if (0 < --hspans)
 				continue;
-			spans = dp->spans;
-			if (1 < spans)
+			hspans = dp->hspans;
+			if (1 < hspans)
 				continue;
 			icol = dp->layout->col;
 			while (maxcol < icol)
Index: TODO
===================================================================
RCS file: /home/cvs/mandoc/mandoc/TODO,v
retrieving revision 1.276
retrieving revision 1.277
diff -LTODO -LTODO -u -p -r1.276 -r1.277
--- TODO
+++ TODO
@@ -168,6 +168,10 @@ are mere guesses, and some may be wrong.
 
 --- missing tbl features -----------------------------------------------
 
+- vertically spanning cells by \^ in the data section
+  pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
+  loc *  exist *  algo *  size *  imp ***
+
 - the "s" layout column specifier is used for placement of data
   into columns, but ignored during column width calculations
   synaptics(4) found by tedu@  Mon, 17 Aug 2015 21:17:42 -0400
@@ -194,10 +198,6 @@ are mere guesses, and some may be wrong.
   in tbl(7) -Tutf-8 output
   suggested by bentley@  Tue, 14 Oct 2014 04:10:55 -0600
   loc *  exist **  algo *  size *  imp **
-
-- implement cell spanning in HTML output
-  pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
-  loc *  exist *  algo **  size **  imp **
 
 - implement table borders in HTML output
   pali dot rohar at gmail dot com 16 Jul 2018 13:03:35 +0200
Index: mandoc.h
===================================================================
RCS file: /home/cvs/mandoc/mandoc/mandoc.h,v
retrieving revision 1.254
retrieving revision 1.255
diff -Lmandoc.h -Lmandoc.h -u -p -r1.254 -r1.255
--- mandoc.h
+++ mandoc.h
@@ -320,7 +320,8 @@ struct	tbl_dat {
 	struct tbl_cell	 *layout; /* layout cell */
 	struct tbl_dat	 *next;
 	char		 *string; /* data (NULL if not TBL_DATA_DATA) */
-	int		  spans; /* how many spans follow */
+	int		  hspans; /* how many horizontal spans follow */
+	int		  vspans; /* how many vertical spans follow */
 	int		  block; /* T{ text block T} */
 	enum tbl_datt	  pos;
 };
Index: tree.c
===================================================================
RCS file: /home/cvs/mandoc/mandoc/tree.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -Ltree.c -Ltree.c -u -p -r1.79 -r1.80
--- tree.c
+++ tree.c
@@ -379,35 +379,41 @@ print_span(const struct tbl_span *sp, in
 	switch (sp->pos) {
 	case TBL_SPAN_HORIZ:
 		putchar('-');
-		return;
+		putchar(' ');
+		break;
 	case TBL_SPAN_DHORIZ:
 		putchar('=');
-		return;
-	default:
+		putchar(' ');
 		break;
-	}
-
-	for (dp = sp->first; dp; dp = dp->next) {
-		switch (dp->pos) {
-		case TBL_DATA_HORIZ:
-		case TBL_DATA_NHORIZ:
-			putchar('-');
-			continue;
-		case TBL_DATA_DHORIZ:
-		case TBL_DATA_NDHORIZ:
-			putchar('=');
-			continue;
-		default:
-			break;
+	default:
+		for (dp = sp->first; dp; dp = dp->next) {
+			switch (dp->pos) {
+			case TBL_DATA_HORIZ:
+			case TBL_DATA_NHORIZ:
+				putchar('-');
+				putchar(' ');
+				continue;
+			case TBL_DATA_DHORIZ:
+			case TBL_DATA_NDHORIZ:
+				putchar('=');
+				putchar(' ');
+				continue;
+			default:
+				break;
+			}
+			printf("[\"%s\"", dp->string ? dp->string : "");
+			if (dp->hspans)
+				printf(">%d", dp->hspans);
+			if (dp->vspans)
+				printf("v%d", dp->vspans);
+			if (dp->layout == NULL)
+				putchar('*');
+			else if (dp->layout->pos == TBL_CELL_DOWN)
+				putchar('^');
+			putchar(']');
+			putchar(' ');
 		}
-		printf("[\"%s\"", dp->string ? dp->string : "");
-		if (dp->spans)
-			printf("(%d)", dp->spans);
-		if (NULL == dp->layout)
-			putchar('*');
-		putchar(']');
-		putchar(' ');
+		break;
 	}
-
 	printf("(tbl) %d:1\n", sp->line);
 }
--
 To unsubscribe send an email to discuss+unsubscribe@mandoc.bsd.lv

  parent reply	other threads:[~2018-11-25 19:34 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-16 11:03 Pali Rohár
2018-07-16 15:29 ` Ingo Schwarze
2018-07-16 16:36   ` Pali Rohár
2018-07-16 17:44     ` Ingo Schwarze
2018-11-24 23:15   ` Ingo Schwarze
2018-11-25 19:34   ` Ingo Schwarze [this message]
2018-11-25 21:25     ` Ingo Schwarze
2018-11-26  8:53       ` Pali Rohár
2018-11-26 21:27   ` Ingo Schwarze
2018-11-26 21:58     ` Pali Rohár
2018-11-26 22:01       ` Pali Rohár
2018-11-26 22:05         ` Pali Rohár
2018-12-01 17:20           ` Ingo Schwarze
2018-12-01 19:35             ` Pali Rohár
2018-12-03 20:46             ` Pali Rohár
2018-12-04  5:33               ` Ingo Schwarze
2018-12-03 22:01             ` Pali Rohár
2018-12-03 22:14               ` Ingo Schwarze
2018-12-03 22:20                 ` Pali Rohár
2018-12-03 22:37                   ` Ingo Schwarze
2018-12-04 16:44                     ` Pali Rohár
2018-12-04 18:04                       ` Ingo Schwarze
2019-01-21  9:39                         ` Pali Rohár
2019-01-21 13:16                           ` Ingo Schwarze
2018-11-29  2:15     ` Ingo Schwarze

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=20181125193434.GC45828@athene.usta.de \
    --to=schwarze@usta.de \
    --cc=discuss@mandoc.bsd.lv \
    --cc=pali.rohar@gmail.com \
    /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).