aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2011-01-01 22:19:15 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2011-01-01 22:19:15 +0000
commit1e982599c7f339de5711a30d937e9f4ab18a529f (patch)
tree82a1fce6498226b5bbd1a76a2551424ce451193d
parent59cd23842b32e78c3cdc0afc0deafb3b7529e470 (diff)
downloadmandoc-1e982599c7f339de5711a30d937e9f4ab18a529f.tar.gz
mandoc-1e982599c7f339de5711a30d937e9f4ab18a529f.tar.zst
mandoc-1e982599c7f339de5711a30d937e9f4ab18a529f.zip
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@).
-rw-r--r--libroff.h4
-rw-r--r--mandoc.h22
-rw-r--r--tbl.c14
-rw-r--r--tbl_layout.c140
4 files changed, 155 insertions, 25 deletions
diff --git a/libroff.h b/libroff.h
index 3c2d6a11..1c9147b4 100644
--- a/libroff.h
+++ b/libroff.h
@@ -1,4 +1,4 @@
-/* $Id: libroff.h,v 1.13 2011/01/01 16:10:40 kristaps Exp $ */
+/* $Id: libroff.h,v 1.14 2011/01/01 22:19:15 kristaps Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -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;
};
diff --git a/mandoc.h b/mandoc.h
index 094241f1..d5b9169b 100644
--- a/mandoc.h
+++ b/mandoc.h
@@ -1,4 +1,4 @@
-/* $Id: mandoc.h,v 1.40 2011/01/01 17:10:20 kristaps Exp $ */
+/* $Id: mandoc.h,v 1.41 2011/01/01 22:19:15 kristaps Exp $ */
/*
* Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -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;
};
/*
diff --git a/tbl.c b/tbl.c
index ba41a3ac..55ea0f34 100644
--- a/tbl.c
+++ b/tbl.c
@@ -1,4 +1,4 @@
-/* $Id: tbl.c,v 1.14 2011/01/01 16:10:40 kristaps Exp $ */
+/* $Id: tbl.c,v 1.15 2011/01/01 22:19:15 kristaps Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -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;
@@ -112,6 +111,11 @@ tbl_free(struct tbl *p)
free(sp);
}
+ while (NULL != (hp = p->first_head)) {
+ p->first_head = hp->next;
+ free(hp);
+ }
+
free(p);
}
diff --git a/tbl_layout.c b/tbl_layout.c
index e482328d..05018f3e 100644
--- a/tbl_layout.c
+++ b/tbl_layout.c
@@ -1,4 +1,4 @@
-/* $Id: tbl_layout.c,v 1.4 2011/01/01 21:23:01 kristaps Exp $ */
+/* $Id: tbl_layout.c,v 1.5 2011/01/01 22:19:15 kristaps Exp $ */
/*
* Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -45,11 +45,15 @@ static const struct tbl_phrase keys[KEYS_MAX] = {
{ '|', 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, const char *p)
/* 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;
+}
+