-/* $Id: tbl_layout.c,v 1.35 2015/01/30 00:29:30 schwarze Exp $ */
+/* $Id: tbl_layout.c,v 1.50 2021/08/10 12:55:04 schwarze Exp $ */
/*
* Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012, 2014, 2015, 2017, 2020, 2021
+ * Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <sys/types.h>
#include <ctype.h>
+#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include "mandoc.h"
#include "mandoc_aux.h"
+#include "mandoc.h"
+#include "tbl.h"
#include "libmandoc.h"
-#include "libroff.h"
+#include "tbl_int.h"
struct tbl_phrase {
char name;
int ln, const char *p, int *pos)
{
char *endptr;
+ unsigned long spacing;
+ size_t sz;
+ int isz;
+ enum mandoc_esc fontesc;
mod:
while (p[*pos] == ' ' || p[*pos] == '\t')
(*pos)++;
goto mod;
}
- mandoc_msg(MANDOCERR_TBLLAYOUT_PAR, tbl->parse,
- ln, *pos, NULL);
+ mandoc_msg(MANDOCERR_TBLLAYOUT_PAR, ln, *pos, NULL);
return;
}
/* Parse numerical spacing from modifier string. */
if (isdigit((unsigned char)p[*pos])) {
- cp->spacing = strtoull(p + *pos, &endptr, 10);
+ if ((spacing = strtoul(p + *pos, &endptr, 10)) > 9)
+ mandoc_msg(MANDOCERR_TBLLAYOUT_SPC, ln, *pos,
+ "%lu", spacing);
+ else
+ cp->spacing = spacing;
*pos = endptr - p;
goto mod;
}
switch (tolower((unsigned char)p[(*pos)++])) {
case 'b':
- /* FALLTHROUGH */
- case 'i':
- /* FALLTHROUGH */
- case 'r':
- (*pos)--;
- break;
+ cp->font = ESCAPE_FONTBOLD;
+ goto mod;
case 'd':
cp->flags |= TBL_CELL_BALIGN;
goto mod;
goto mod;
case 'f':
break;
+ case 'i':
+ cp->font = ESCAPE_FONTITALIC;
+ goto mod;
case 'm':
- mandoc_msg(MANDOCERR_TBLLAYOUT_MOD, tbl->parse,
- ln, *pos, "m");
+ mandoc_msg(MANDOCERR_TBLLAYOUT_MOD, ln, *pos, "m");
goto mod;
case 'p':
- /* FALLTHROUGH */
case 'v':
if (p[*pos] == '-' || p[*pos] == '+')
(*pos)++;
case 'u':
cp->flags |= TBL_CELL_UP;
goto mod;
- case 'w': /* XXX for now, ignore minimal column width */
+ case 'w':
+ sz = 0;
+ if (p[*pos] == '(') {
+ (*pos)++;
+ while (p[*pos + sz] != '\0' && p[*pos + sz] != ')')
+ sz++;
+ } else
+ while (isdigit((unsigned char)p[*pos + sz]))
+ sz++;
+ if (sz) {
+ free(cp->wstr);
+ cp->wstr = mandoc_strndup(p + *pos, sz);
+ *pos += sz;
+ if (p[*pos] == ')')
+ (*pos)++;
+ }
goto mod;
case 'x':
cp->flags |= TBL_CELL_WMAX;
cp->vert++;
else
mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
- tbl->parse, ln, *pos - 1, NULL);
+ ln, *pos - 1, NULL);
goto mod;
default:
- mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
+ mandoc_msg(MANDOCERR_TBLLAYOUT_CHAR,
ln, *pos - 1, "%c", p[*pos - 1]);
goto mod;
}
- switch (tolower((unsigned char)p[(*pos)++])) {
- case '3':
- /* FALLTHROUGH */
- case 'b':
- cp->flags |= TBL_CELL_BOLD;
- goto mod;
- case '2':
- /* FALLTHROUGH */
- case 'i':
- cp->flags |= TBL_CELL_ITALIC;
- goto mod;
- case '1':
- /* FALLTHROUGH */
- case 'r':
+ while (p[*pos] == ' ' || p[*pos] == '\t')
+ (*pos)++;
+
+ /* Ignore parenthised font names for now. */
+
+ if (p[*pos] == '(')
goto mod;
+
+ isz = 0;
+ if (p[*pos] != '\0')
+ isz++;
+ if (strchr(" \t.", p[*pos + isz]) == NULL)
+ isz++;
+
+ fontesc = mandoc_font(p + *pos, isz);
+
+ switch (fontesc) {
+ case ESCAPE_FONTPREV:
+ case ESCAPE_ERROR:
+ mandoc_msg(MANDOCERR_FT_BAD,
+ ln, *pos, "TS %s", p + *pos - 1);
+ break;
default:
- mandoc_vmsg(MANDOCERR_FT_BAD, tbl->parse,
- ln, *pos - 1, "TS f%c", p[*pos - 1]);
- goto mod;
+ cp->font = fontesc;
+ break;
}
+ *pos += isz;
+ goto mod;
}
static void
rp->vert++;
else
mandoc_msg(MANDOCERR_TBLLAYOUT_VERT,
- tbl->parse, ln, *pos, NULL);
+ ln, *pos, NULL);
}
(*pos)++;
}
break;
if (i == KEYS_MAX) {
- mandoc_vmsg(MANDOCERR_TBLLAYOUT_CHAR, tbl->parse,
+ mandoc_msg(MANDOCERR_TBLLAYOUT_CHAR,
ln, *pos, "%c", p[*pos]);
(*pos)++;
goto again;
if (c == TBL_CELL_SPAN) {
if (rp->last == NULL)
- mandoc_msg(MANDOCERR_TBLLAYOUT_SPAN,
- tbl->parse, ln, *pos, NULL);
+ mandoc_msg(MANDOCERR_TBLLAYOUT_SPAN, ln, *pos, NULL);
else if (rp->last->pos == TBL_CELL_HORIZ ||
rp->last->pos == TBL_CELL_DHORIZ)
c = rp->last->pos;
} else if (c == TBL_CELL_DOWN && rp == tbl->first_row)
- mandoc_msg(MANDOCERR_TBLLAYOUT_DOWN,
- tbl->parse, ln, *pos, NULL);
+ mandoc_msg(MANDOCERR_TBLLAYOUT_DOWN, ln, *pos, NULL);
(*pos)++;
}
if (tbl->first_row->first == NULL) {
mandoc_msg(MANDOCERR_TBLLAYOUT_NONE,
- tbl->parse, ln, pos, NULL);
+ ln, pos, NULL);
cell_alloc(tbl, tbl->first_row,
TBL_CELL_LEFT);
+ if (tbl->opts.lvert < tbl->first_row->vert)
+ tbl->opts.lvert = tbl->first_row->vert;
return;
}
if (tbl->opts.lvert < rp->vert)
tbl->opts.lvert = rp->vert;
if (rp->last != NULL &&
- rp->last->head == tbl->last_head &&
+ rp->last->col + 1 == tbl->opts.cols &&
tbl->opts.rvert < rp->last->vert)
tbl->opts.rvert = rp->last->vert;
rp->next->first == NULL) {
free(rp->next);
rp->next = NULL;
+ tbl->last_row = rp;
}
}
return;
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->spacing = SIZE_MAX;
+ p->font = ESCAPE_FONTROMAN;
+ 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;
-
- /* Re-use header. */
-
- if (h) {
- p->head = h;
- return(p);
- }
-
- hp = mandoc_calloc(1, sizeof(struct tbl_head));
- hp->ident = tbl->opts.cols++;
-
- if (tbl->last_head) {
- hp->prev = tbl->last_head;
- tbl->last_head->next = hp;
- } else
- tbl->first_head = hp;
- tbl->last_head = hp;
+ if (tbl->opts.cols <= p->col)
+ tbl->opts.cols = p->col + 1;
- p->head = hp;
- return(p);
+ return p;
}