From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (kristaps@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.3/8.14.3) with ESMTP id p01MJFPJ009309 for ; Sat, 1 Jan 2011 17:19:15 -0500 (EST) Received: (from kristaps@localhost) by krisdoz.my.domain (8.14.3/8.14.3/Submit) id p01MJFM6023760; Sat, 1 Jan 2011 17:19:15 -0500 (EST) Date: Sat, 1 Jan 2011 17:19:15 -0500 (EST) Message-Id: <201101012219.p01MJFM6023760@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: kristaps@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Plug in the "head" concept for tables. X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 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