source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Plug in the "head" concept for tables.
@ 2011-01-01 22:19 kristaps
  0 siblings, 0 replies; only message in thread
From: kristaps @ 2011-01-01 22:19 UTC (permalink / raw)
  To: source

Log Message:
-----------
Plug in the "head" concept for tables.  A tbl_head specifies the full
layout for each row, including vertical spacers.  One grabs the tbl_head
for a row and iterates through each entry, plugging data from the
tbl_span into the header as appropriate.

This is pulled in more or less verbatim from tbl.bsd.lv.  In fact, this
is verbatim except that lists macros are made into hard-coded lists (for
compatibility, as long-ago noted by joerg@).

Modified Files:
--------------
    mdocml:
        libroff.h
        mandoc.h
        tbl.c
        tbl_layout.c

Revision Data
-------------
Index: tbl_layout.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/tbl_layout.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -Ltbl_layout.c -Ltbl_layout.c -u -p -r1.4 -r1.5
--- tbl_layout.c
+++ tbl_layout.c
@@ -45,11 +45,15 @@ static	const struct tbl_phrase keys[KEYS
 	{ '|',		 TBL_CELL_VERT }
 };
 
-static	int	 mods(struct tbl *, struct tbl_cell *, 
-			int, const char *, int *);
-static	int	 cell(struct tbl *, struct tbl_row *, 
-			int, const char *, int *);
-static	void	 row(struct tbl *, int, const char *, int *);
+static	int		 mods(struct tbl *, struct tbl_cell *, 
+				int, const char *, int *);
+static	int		 cell(struct tbl *, struct tbl_row *, 
+				int, const char *, int *);
+static	void		 row(struct tbl *, int, const char *, int *);
+static	struct tbl_cell *cell_alloc(struct tbl *, 
+				struct tbl_row *, enum tbl_cellt);
+static	void		 head_adjust(const struct tbl_cell *, 
+				struct tbl_head *);
 
 static int
 mods(struct tbl *tbl, struct tbl_cell *cp, 
@@ -153,7 +157,6 @@ static int
 cell(struct tbl *tbl, struct tbl_row *rp, 
 		int ln, const char *p, int *pos)
 {
-	struct tbl_cell	*cp;
 	int		 i;
 	enum tbl_cellt	 c;
 
@@ -189,16 +192,7 @@ cell(struct tbl *tbl, struct tbl_row *rp
 
 	/* Allocate cell then parse its modifiers. */
 
-	cp = mandoc_calloc(1, sizeof(struct tbl_cell));
-	cp->pos = c;
-
-	if (rp->last) {
-		rp->last->next = cp;
-		rp->last = cp;
-	} else
-		rp->last = rp->first = cp;
-
-	return(mods(tbl, cp, ln, p, pos));
+	return(mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos));
 }
 
 
@@ -253,7 +247,6 @@ cell:
 	/* NOTREACHED */
 }
 
-
 int
 tbl_layout(struct tbl *tbl, int ln, const char *p)
 {
@@ -265,3 +258,114 @@ tbl_layout(struct tbl *tbl, int ln, cons
 	/* Always succeed. */
 	return(1);
 }
+
+static struct tbl_cell *
+cell_alloc(struct tbl *tbl, struct tbl_row *rp, enum tbl_cellt pos)
+{
+	struct tbl_cell	*p, *pp;
+	struct tbl_head	*h, *hp;
+
+	p = mandoc_calloc(1, sizeof(struct tbl_cell));
+
+	if (NULL != (pp = rp->last)) {
+		rp->last->next = p;
+		rp->last = p;
+	} else
+		rp->last = rp->first = p;
+
+	p->pos = pos;
+
+	/*
+	 * This is a little bit complicated.  Here we determine the
+	 * header the corresponds to a cell.  We add headers dynamically
+	 * when need be or re-use them, otherwise.  As an example, given
+	 * the following:
+	 *
+	 * 	1  c || l 
+	 * 	2  | c | l
+	 * 	3  l l
+	 * 	3  || c | l |.
+	 *
+	 * We first add the new headers (as there are none) in (1); then
+	 * in (2) we insert the first spanner (as it doesn't match up
+	 * with the header); then we re-use the prior data headers,
+	 * skipping over the spanners; then we re-use everything and add
+	 * a last spanner.  Note that VERT headers are made into DVERT
+	 * ones.
+	 */
+
+	h = pp ? pp->head->prev : tbl->first_head;
+
+	if (h) {
+		/* Re-use data header. */
+		if (TBL_HEAD_DATA == h->pos && 
+				(TBL_CELL_VERT != p->pos &&
+				 TBL_CELL_DVERT != p->pos)) {
+			p->head = h;
+			return(p);
+		}
+
+		/* Re-use spanner header. */
+		if (TBL_HEAD_DATA != h->pos && 
+				(TBL_CELL_VERT == p->pos ||
+				 TBL_CELL_DVERT == p->pos)) {
+			head_adjust(p, h);
+			p->head = h;
+			return(p);
+		}
+
+		/* Right-shift headers with a new spanner. */
+		if (TBL_HEAD_DATA == h->pos && 
+				(TBL_CELL_VERT == p->pos ||
+				 TBL_CELL_DVERT == p->pos)) {
+			hp = mandoc_calloc(1, sizeof(struct tbl_head));
+			hp->prev = h->prev;
+			if (h->prev)
+				h->prev->next = hp;
+			h->prev = hp;
+			hp->next = h;
+			head_adjust(p, hp);
+			p->head = hp;
+			return(p);
+		}
+
+		if (NULL != (h = h->next)) {
+			head_adjust(p, h);
+			p->head = h;
+			return(p);
+		}
+
+		/* Fall through to default case... */
+	}
+
+	hp = mandoc_calloc(1, sizeof(struct tbl_head));
+
+	if (tbl->last_head) {
+		hp->prev = tbl->last_head;
+		tbl->last_head->next = hp;
+		tbl->last_head = hp;
+	} else
+		tbl->last_head = tbl->first_head = hp;
+
+	head_adjust(p, hp);
+	p->head = hp;
+	return(p);
+}
+
+static void
+head_adjust(const struct tbl_cell *cell, struct tbl_head *head)
+{
+	if (TBL_CELL_VERT != cell->pos &&
+			TBL_CELL_DVERT != cell->pos) {
+		head->pos = TBL_HEAD_DATA;
+		return;
+	}
+
+	if (TBL_CELL_VERT == cell->pos)
+		if (TBL_HEAD_DVERT != head->pos)
+			head->pos = TBL_HEAD_VERT;
+
+	if (TBL_CELL_DVERT == cell->pos)
+		head->pos = TBL_HEAD_DVERT;
+}
+
Index: tbl.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/tbl.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -Ltbl.c -Ltbl.c -u -p -r1.14 -r1.15
--- tbl.c
+++ tbl.c
@@ -87,9 +87,9 @@ tbl_free(struct tbl *p)
 	struct tbl_cell	*cp;
 	struct tbl_span	*sp;
 	struct tbl_dat	*dp;
+	struct tbl_head	*hp;
 
-	while (p->first_row) {
-		rp = p->first_row;
+	while (NULL != (rp = p->first_row)) {
 		p->first_row = rp->next;
 		while (rp->first) {
 			cp = rp->first;
@@ -99,8 +99,7 @@ tbl_free(struct tbl *p)
 		free(rp);
 	}
 
-	while (p->first_span) {
-		sp = p->first_span;
+	while (NULL != (sp = p->first_span)) {
 		p->first_span = sp->next;
 		while (sp->first) {
 			dp = sp->first;
@@ -110,6 +109,11 @@ tbl_free(struct tbl *p)
 			free(dp);
 		}
 		free(sp);
+	}
+
+	while (NULL != (hp = p->first_head)) {
+		p->first_head = hp->next;
+		free(hp);
 	}
 
 	free(p);
Index: mandoc.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/mandoc.h,v
retrieving revision 1.40
retrieving revision 1.41
diff -Lmandoc.h -Lmandoc.h -u -p -r1.40 -r1.41
--- mandoc.h
+++ mandoc.h
@@ -140,6 +140,25 @@ enum	mandocerr {
 	MANDOCERR_MAX
 };
 
+enum	tbl_headt {
+	TBL_HEAD_DATA, /* plug in data from tbl_dat */
+	TBL_HEAD_VERT, /* vertical spacer */
+	TBL_HEAD_DVERT  /* double-vertical spacer */
+};
+
+/*
+ * The head of a table specifies all of its columns.  When formatting a
+ * tbl_span, iterate over these and plug in data from the tbl_span when
+ * appropriate, using tbl_cell as a guide to placement.
+ */
+struct	tbl_head {
+	enum tbl_headt	  pos;
+	int		  width; /* width of cell in fixed chars */
+	int		  decimal; /* decimal point position */
+	struct tbl_head	 *next;
+	struct tbl_head	 *prev;
+};
+
 enum	tbl_cellt {
 	TBL_CELL_CENTRE, /* c, C */
 	TBL_CELL_RIGHT, /* r, R */
@@ -170,6 +189,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 */
+	struct tbl_head	 *head;
 };
 
 /*
Index: libroff.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/libroff.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -Llibroff.h -Llibroff.h -u -p -r1.13 -r1.14
--- libroff.h
+++ libroff.h
@@ -47,6 +47,8 @@ struct	tbl {
 	struct tbl_row	 *last_row;
 	struct tbl_span	 *first_span;
 	struct tbl_span	 *last_span;
+	struct tbl_head	 *first_head;
+	struct tbl_head	 *last_head;
 	struct tbl	 *next;
 };
 
--
 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:[~2011-01-01 22:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-01-01 22:19 mdocml: Plug in the "head" concept for tables kristaps

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