tbl_layout.c revision 371584c2eae4cf827fd406ba26c14f021adaaa70
371584c2eae4cf827fd406ba26c14f021adaaa70Yuri Pankov/* $Id: tbl_layout.c,v 1.41 2015/10/12 00:08:16 schwarze Exp $ */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * Permission to use, copy, modify, and distribute this software for any
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * purpose with or without fee is hereby granted, provided that the above
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * copyright notice and this permission notice appear in all copies.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov#define KEYS_MAX ((int)(sizeof(keys)/sizeof(keys[0])))
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic void mods(struct tbl_node *, struct tbl_cell *,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int, const char *, int *);
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovstatic void cell(struct tbl_node *, struct tbl_row *,
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore int, const char *, int *);
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amorestatic struct tbl_cell *cell_alloc(struct tbl_node *, struct tbl_row *,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Row delimiters and cell specifiers end modifier lists. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (strchr(".,-=^_ACLNRSaclnrs", p[*pos]) != NULL)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Throw away parenthesised expression. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Parse numerical spacing from modifier string. */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore switch (tolower((unsigned char)p[(*pos)++])) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov case 'w': /* XXX for now, ignore minimal column width */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Ignore parenthised font names for now. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Support only one-character font-names for now. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov if (p[*pos] == '\0' || (p[*pos + 1] != ' ' && p[*pos + 1] != '.')) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov switch (p[(*pos)++]) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Handle leading vertical lines */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov while (p[*pos] == ' ' || p[*pos] == '\t' || p[*pos] == '|') {
698f87a48e2e945bfe5493ce168e0d0ae1cedd5cGarrett D'Amore /* Parse the column position (`c', `l', `r', ...). */
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore for (i = 0; i < KEYS_MAX; i++)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore if (tolower((unsigned char)p[*pos]) == keys[i].name)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Special cases of spanners. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov } else if (c == TBL_CELL_DOWN && rp == tbl->first_row)
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amore /* Allocate cell then parse its modifiers. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovtbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos)
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* Skip whitespace before and after each cell. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov switch (p[pos]) {
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * When the layout is completely empty,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * default to one left-justified column.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * Search for the widest line
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * along the left and right margins.
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov /* If the last line is empty, drop it. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov default: /* Cell. */
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * If the last line had at least one cell,
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankov * start a new one; otherwise, continue it.
95c635efb7c3b86efc493e0447eaec7aecca3f0fGarrett D'Amorestatic struct tbl_cell *
260e9a87725c090ba5835b1f9f0b62fa2f96036fYuri Pankovcell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos)