1*99db7d0eSSascha Wildner /* $Id: term_tab.c,v 1.6 2020/06/22 19:20:40 schwarze Exp $ */
254ba9607SSascha Wildner /*
354ba9607SSascha Wildner * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
454ba9607SSascha Wildner *
554ba9607SSascha Wildner * Permission to use, copy, modify, and distribute this software for any
654ba9607SSascha Wildner * purpose with or without fee is hereby granted, provided that the above
754ba9607SSascha Wildner * copyright notice and this permission notice appear in all copies.
854ba9607SSascha Wildner *
954ba9607SSascha Wildner * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1054ba9607SSascha Wildner * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1154ba9607SSascha Wildner * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1254ba9607SSascha Wildner * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1354ba9607SSascha Wildner * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1454ba9607SSascha Wildner * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1554ba9607SSascha Wildner * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1654ba9607SSascha Wildner */
17*99db7d0eSSascha Wildner #include "config.h"
18*99db7d0eSSascha Wildner
1954ba9607SSascha Wildner #include <sys/types.h>
2054ba9607SSascha Wildner
2154ba9607SSascha Wildner #include <stddef.h>
2254ba9607SSascha Wildner
2354ba9607SSascha Wildner #include "mandoc_aux.h"
2454ba9607SSascha Wildner #include "out.h"
2554ba9607SSascha Wildner #include "term.h"
2654ba9607SSascha Wildner
2754ba9607SSascha Wildner struct tablist {
2854ba9607SSascha Wildner size_t *t; /* Allocated array of tab positions. */
2954ba9607SSascha Wildner size_t s; /* Allocated number of positions. */
3054ba9607SSascha Wildner size_t n; /* Currently used number of positions. */
3154ba9607SSascha Wildner };
3254ba9607SSascha Wildner
3354ba9607SSascha Wildner static struct {
3454ba9607SSascha Wildner struct tablist a; /* All tab positions for lookup. */
3554ba9607SSascha Wildner struct tablist p; /* Periodic tab positions to add. */
3654ba9607SSascha Wildner size_t d; /* Default tab width in units of n. */
3754ba9607SSascha Wildner } tabs;
3854ba9607SSascha Wildner
3954ba9607SSascha Wildner
4054ba9607SSascha Wildner void
term_tab_set(const struct termp * p,const char * arg)4154ba9607SSascha Wildner term_tab_set(const struct termp *p, const char *arg)
4254ba9607SSascha Wildner {
4354ba9607SSascha Wildner static int recording_period;
4454ba9607SSascha Wildner
4554ba9607SSascha Wildner struct roffsu su;
4654ba9607SSascha Wildner struct tablist *tl;
4754ba9607SSascha Wildner size_t pos;
4854ba9607SSascha Wildner int add;
4954ba9607SSascha Wildner
5054ba9607SSascha Wildner /* Special arguments: clear all tabs or switch lists. */
5154ba9607SSascha Wildner
5254ba9607SSascha Wildner if (arg == NULL) {
5354ba9607SSascha Wildner tabs.a.n = tabs.p.n = 0;
5454ba9607SSascha Wildner recording_period = 0;
5554ba9607SSascha Wildner if (tabs.d == 0) {
5654ba9607SSascha Wildner a2roffsu(".8i", &su, SCALE_IN);
5754ba9607SSascha Wildner tabs.d = term_hen(p, &su);
5854ba9607SSascha Wildner }
5954ba9607SSascha Wildner return;
6054ba9607SSascha Wildner }
6154ba9607SSascha Wildner if (arg[0] == 'T' && arg[1] == '\0') {
6254ba9607SSascha Wildner recording_period = 1;
6354ba9607SSascha Wildner return;
6454ba9607SSascha Wildner }
6554ba9607SSascha Wildner
6654ba9607SSascha Wildner /* Parse the sign, the number, and the unit. */
6754ba9607SSascha Wildner
6854ba9607SSascha Wildner if (*arg == '+') {
6954ba9607SSascha Wildner add = 1;
7054ba9607SSascha Wildner arg++;
7154ba9607SSascha Wildner } else
7254ba9607SSascha Wildner add = 0;
7354ba9607SSascha Wildner if (a2roffsu(arg, &su, SCALE_EM) == NULL)
7454ba9607SSascha Wildner return;
7554ba9607SSascha Wildner
7654ba9607SSascha Wildner /* Select the list, and extend it if it is full. */
7754ba9607SSascha Wildner
7854ba9607SSascha Wildner tl = recording_period ? &tabs.p : &tabs.a;
7954ba9607SSascha Wildner if (tl->n >= tl->s) {
8054ba9607SSascha Wildner tl->s += 8;
8154ba9607SSascha Wildner tl->t = mandoc_reallocarray(tl->t, tl->s, sizeof(*tl->t));
8254ba9607SSascha Wildner }
8354ba9607SSascha Wildner
8454ba9607SSascha Wildner /* Append the new position. */
8554ba9607SSascha Wildner
8654ba9607SSascha Wildner pos = term_hen(p, &su);
8754ba9607SSascha Wildner tl->t[tl->n] = pos;
8854ba9607SSascha Wildner if (add && tl->n)
8954ba9607SSascha Wildner tl->t[tl->n] += tl->t[tl->n - 1];
9054ba9607SSascha Wildner tl->n++;
9154ba9607SSascha Wildner }
9254ba9607SSascha Wildner
9354ba9607SSascha Wildner /*
9454ba9607SSascha Wildner * Simplified version without a parser,
9554ba9607SSascha Wildner * never incremental, never periodic, for use by tbl(7).
9654ba9607SSascha Wildner */
9754ba9607SSascha Wildner void
term_tab_iset(size_t inc)9854ba9607SSascha Wildner term_tab_iset(size_t inc)
9954ba9607SSascha Wildner {
10054ba9607SSascha Wildner if (tabs.a.n >= tabs.a.s) {
10154ba9607SSascha Wildner tabs.a.s += 8;
10254ba9607SSascha Wildner tabs.a.t = mandoc_reallocarray(tabs.a.t, tabs.a.s,
10354ba9607SSascha Wildner sizeof(*tabs.a.t));
10454ba9607SSascha Wildner }
10554ba9607SSascha Wildner tabs.a.t[tabs.a.n++] = inc;
10654ba9607SSascha Wildner }
10754ba9607SSascha Wildner
10854ba9607SSascha Wildner size_t
term_tab_next(size_t prev)10954ba9607SSascha Wildner term_tab_next(size_t prev)
11054ba9607SSascha Wildner {
11154ba9607SSascha Wildner size_t i, j;
11254ba9607SSascha Wildner
11354ba9607SSascha Wildner for (i = 0;; i++) {
11454ba9607SSascha Wildner if (i == tabs.a.n) {
11554ba9607SSascha Wildner if (tabs.p.n == 0)
11654ba9607SSascha Wildner return prev;
11754ba9607SSascha Wildner tabs.a.n += tabs.p.n;
11854ba9607SSascha Wildner if (tabs.a.s < tabs.a.n) {
11954ba9607SSascha Wildner tabs.a.s = tabs.a.n;
12054ba9607SSascha Wildner tabs.a.t = mandoc_reallocarray(tabs.a.t,
12154ba9607SSascha Wildner tabs.a.s, sizeof(*tabs.a.t));
12254ba9607SSascha Wildner }
12354ba9607SSascha Wildner for (j = 0; j < tabs.p.n; j++)
12454ba9607SSascha Wildner tabs.a.t[i + j] = tabs.p.t[j] +
12554ba9607SSascha Wildner (i ? tabs.a.t[i - 1] : 0);
12654ba9607SSascha Wildner }
12754ba9607SSascha Wildner if (prev < tabs.a.t[i])
12854ba9607SSascha Wildner return tabs.a.t[i];
12954ba9607SSascha Wildner }
13054ba9607SSascha Wildner }
131