=================================================================== RCS file: /cvs/mandoc/tbl_layout.c,v retrieving revision 1.32 retrieving revision 1.39 diff -u -p -r1.32 -r1.39 --- mandoc/tbl_layout.c 2015/01/26 18:42:30 1.32 +++ mandoc/tbl_layout.c 2015/04/29 12:44:58 1.39 @@ -1,4 +1,4 @@ -/* $Id: tbl_layout.c,v 1.32 2015/01/26 18:42:30 schwarze Exp $ */ +/* $Id: tbl_layout.c,v 1.39 2015/04/29 12:44:58 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons * Copyright (c) 2012, 2014, 2015 Ingo Schwarze @@ -54,7 +54,7 @@ static void mods(struct tbl_node *, struct tbl_cell static void cell(struct tbl_node *, struct tbl_row *, int, const char *, int *); static struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *, - enum tbl_cellt, int vert); + enum tbl_cellt); static void @@ -69,7 +69,7 @@ mod: /* Row delimiters and cell specifiers end modifier lists. */ - if (strchr(".,-=^_ACLNRSaclnrs|", p[*pos]) != NULL) + if (strchr(".,-=^_ACLNRSaclnrs", p[*pos]) != NULL) return; /* Throw away parenthesised expression. */ @@ -97,12 +97,8 @@ mod: switch (tolower((unsigned char)p[(*pos)++])) { case 'b': - /* FALLTHROUGH */ - case 'i': - /* FALLTHROUGH */ - case 'r': - (*pos)--; - break; + cp->flags |= TBL_CELL_BOLD; + goto mod; case 'd': cp->flags |= TBL_CELL_BALIGN; goto mod; @@ -111,6 +107,9 @@ mod: goto mod; case 'f': break; + case 'i': + cp->flags |= TBL_CELL_ITALIC; + goto mod; case 'm': mandoc_msg(MANDOCERR_TBLLAYOUT_MOD, tbl->parse, ln, *pos, "m"); @@ -137,26 +136,50 @@ mod: case 'z': cp->flags |= TBL_CELL_WIGN; goto mod; + case '|': + if (cp->vert < 2) + cp->vert++; + else + mandoc_msg(MANDOCERR_TBLLAYOUT_VERT, + tbl->parse, ln, *pos - 1, NULL); + goto mod; default: mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse, ln, *pos - 1, "%c", p[*pos - 1]); goto mod; } - switch (tolower((unsigned char)p[(*pos)++])) { + /* Ignore parenthised font names for now. */ + + if (p[*pos] == '(') + goto mod; + + /* Support only one-character font-names for now. */ + + if (p[*pos] == '\0' || (p[*pos + 1] != ' ' && p[*pos + 1] != '.')) { + mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse, + ln, *pos, "TS %s", p + *pos - 1); + if (p[*pos] != '\0') + (*pos)++; + if (p[*pos] != '\0') + (*pos)++; + goto mod; + } + + switch (p[(*pos)++]) { case '3': /* FALLTHROUGH */ - case 'b': + case 'B': cp->flags |= TBL_CELL_BOLD; goto mod; case '2': /* FALLTHROUGH */ - case 'i': + case 'I': cp->flags |= TBL_CELL_ITALIC; goto mod; case '1': /* FALLTHROUGH */ - case 'r': + case 'R': goto mod; default: mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse, @@ -169,17 +192,15 @@ static void cell(struct tbl_node *tbl, struct tbl_row *rp, int ln, const char *p, int *pos) { - int vert, i; + int i; enum tbl_cellt c; - /* Handle vertical lines. */ + /* Handle leading vertical lines */ - vert = 0; -again: while (p[*pos] == ' ' || p[*pos] == '\t' || p[*pos] == '|') { if (p[*pos] == '|') { - if (vert < 2) - vert++; + if (rp->vert < 2) + rp->vert++; else mandoc_msg(MANDOCERR_TBLLAYOUT_VERT, tbl->parse, ln, *pos, NULL); @@ -187,12 +208,12 @@ again: (*pos)++; } - /* Handle trailing vertical lines */ +again: + while (p[*pos] == ' ' || p[*pos] == '\t') + (*pos)++; - if ('.' == p[*pos] || '\0' == p[*pos]) { - rp->vert = vert; + if (p[*pos] == '.' || p[*pos] == '\0') return; - } /* Parse the column position (`c', `l', `r', ...). */ @@ -225,18 +246,15 @@ again: /* Allocate cell then parse its modifiers. */ - mods(tbl, cell_alloc(tbl, rp, c, vert), ln, p, pos); + mods(tbl, cell_alloc(tbl, rp, c), ln, p, pos); } void -tbl_layout(struct tbl_node *tbl, int ln, const char *p) +tbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos) { struct tbl_row *rp; - int pos; - pos = 0; rp = NULL; - for (;;) { /* Skip whitespace before and after each cell. */ @@ -253,69 +271,89 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p case '.': /* End of layout. */ pos++; tbl->part = TBL_PART_DATA; - if (tbl->first_row != NULL) + + /* + * When the layout is completely empty, + * default to one left-justified column. + */ + + if (tbl->first_row == NULL) { + tbl->first_row = tbl->last_row = + mandoc_calloc(1, sizeof(*rp)); + } + if (tbl->first_row->first == NULL) { + mandoc_msg(MANDOCERR_TBLLAYOUT_NONE, + tbl->parse, ln, pos, NULL); + cell_alloc(tbl, tbl->first_row, + TBL_CELL_LEFT); return; - mandoc_msg(MANDOCERR_TBLLAYOUT_NONE, - tbl->parse, ln, pos, NULL); - rp = mandoc_calloc(1, sizeof(*rp)); - cell_alloc(tbl, rp, TBL_CELL_LEFT, 0); - tbl->first_row = tbl->last_row = rp; + } + + /* + * Search for the widest line + * along the left and right margins. + */ + + for (rp = tbl->first_row; rp; rp = rp->next) { + if (tbl->opts.lvert < rp->vert) + tbl->opts.lvert = rp->vert; + if (rp->last != NULL && + rp->last->col + 1 == tbl->opts.cols && + tbl->opts.rvert < rp->last->vert) + tbl->opts.rvert = rp->last->vert; + + /* If the last line is empty, drop it. */ + + if (rp->next != NULL && + rp->next->first == NULL) { + free(rp->next); + rp->next = NULL; + tbl->last_row = rp; + } + } return; default: /* Cell. */ break; } - if (rp == NULL) { /* First cell on this line. */ - rp = mandoc_calloc(1, sizeof(*rp)); - if (tbl->last_row) - tbl->last_row->next = rp; - else - tbl->first_row = rp; - tbl->last_row = rp; + /* + * If the last line had at least one cell, + * start a new one; otherwise, continue it. + */ + + if (rp == NULL) { + if (tbl->last_row == NULL || + tbl->last_row->first != NULL) { + rp = mandoc_calloc(1, sizeof(*rp)); + if (tbl->last_row) + tbl->last_row->next = rp; + else + tbl->first_row = rp; + tbl->last_row = rp; + } else + rp = tbl->last_row; } cell(tbl, rp, ln, p, &pos); } } static struct tbl_cell * -cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos, - int vert) +cell_alloc(struct tbl_node *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)); + p = mandoc_calloc(1, sizeof(*p)); + p->pos = pos; - if (NULL != (pp = rp->last)) { + if ((pp = rp->last) != NULL) { pp->next = p; - h = pp->head->next; - } else { + p->col = pp->col + 1; + } else rp->first = p; - h = tbl->first_head; - } rp->last = p; - p->pos = pos; - p->vert = vert; + if (tbl->opts.cols <= p->col) + tbl->opts.cols = p->col + 1; - /* Re-use header. */ - - if (h) { - p->head = h; - return(p); - } - - hp = mandoc_calloc(1, sizeof(struct tbl_head)); - hp->ident = tbl->opts.cols++; - hp->vert = vert; - - if (tbl->last_head) { - hp->prev = tbl->last_head; - tbl->last_head->next = hp; - } else - tbl->first_head = hp; - tbl->last_head = hp; - - p->head = hp; return(p); }