1*4d131170SRobert Mustacchi /* $Id: term_tab.c,v 1.6 2020/06/22 19:20:40 schwarze Exp $ */
2c66b8046SYuri Pankov /*
3c66b8046SYuri Pankov * Copyright (c) 2017 Ingo Schwarze <schwarze@openbsd.org>
4c66b8046SYuri Pankov *
5c66b8046SYuri Pankov * Permission to use, copy, modify, and distribute this software for any
6c66b8046SYuri Pankov * purpose with or without fee is hereby granted, provided that the above
7c66b8046SYuri Pankov * copyright notice and this permission notice appear in all copies.
8c66b8046SYuri Pankov *
9c66b8046SYuri Pankov * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10c66b8046SYuri Pankov * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11c66b8046SYuri Pankov * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12c66b8046SYuri Pankov * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13c66b8046SYuri Pankov * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14c66b8046SYuri Pankov * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15c66b8046SYuri Pankov * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16c66b8046SYuri Pankov */
17*4d131170SRobert Mustacchi #include "config.h"
18*4d131170SRobert Mustacchi
19c66b8046SYuri Pankov #include <sys/types.h>
20c66b8046SYuri Pankov
21c66b8046SYuri Pankov #include <stddef.h>
22c66b8046SYuri Pankov
23c66b8046SYuri Pankov #include "mandoc_aux.h"
24c66b8046SYuri Pankov #include "out.h"
25c66b8046SYuri Pankov #include "term.h"
26c66b8046SYuri Pankov
27c66b8046SYuri Pankov struct tablist {
28c66b8046SYuri Pankov size_t *t; /* Allocated array of tab positions. */
29c66b8046SYuri Pankov size_t s; /* Allocated number of positions. */
30c66b8046SYuri Pankov size_t n; /* Currently used number of positions. */
31c66b8046SYuri Pankov };
32c66b8046SYuri Pankov
33c66b8046SYuri Pankov static struct {
34c66b8046SYuri Pankov struct tablist a; /* All tab positions for lookup. */
35c66b8046SYuri Pankov struct tablist p; /* Periodic tab positions to add. */
36c66b8046SYuri Pankov size_t d; /* Default tab width in units of n. */
37c66b8046SYuri Pankov } tabs;
38c66b8046SYuri Pankov
39c66b8046SYuri Pankov
40c66b8046SYuri Pankov void
term_tab_set(const struct termp * p,const char * arg)41c66b8046SYuri Pankov term_tab_set(const struct termp *p, const char *arg)
42c66b8046SYuri Pankov {
43c66b8046SYuri Pankov static int recording_period;
44c66b8046SYuri Pankov
45c66b8046SYuri Pankov struct roffsu su;
46c66b8046SYuri Pankov struct tablist *tl;
47c66b8046SYuri Pankov size_t pos;
48c66b8046SYuri Pankov int add;
49c66b8046SYuri Pankov
50c66b8046SYuri Pankov /* Special arguments: clear all tabs or switch lists. */
51c66b8046SYuri Pankov
52c66b8046SYuri Pankov if (arg == NULL) {
53c66b8046SYuri Pankov tabs.a.n = tabs.p.n = 0;
54c66b8046SYuri Pankov recording_period = 0;
55c66b8046SYuri Pankov if (tabs.d == 0) {
56c66b8046SYuri Pankov a2roffsu(".8i", &su, SCALE_IN);
57c66b8046SYuri Pankov tabs.d = term_hen(p, &su);
58c66b8046SYuri Pankov }
59c66b8046SYuri Pankov return;
60c66b8046SYuri Pankov }
61c66b8046SYuri Pankov if (arg[0] == 'T' && arg[1] == '\0') {
62c66b8046SYuri Pankov recording_period = 1;
63c66b8046SYuri Pankov return;
64c66b8046SYuri Pankov }
65c66b8046SYuri Pankov
66c66b8046SYuri Pankov /* Parse the sign, the number, and the unit. */
67c66b8046SYuri Pankov
68c66b8046SYuri Pankov if (*arg == '+') {
69c66b8046SYuri Pankov add = 1;
70c66b8046SYuri Pankov arg++;
71c66b8046SYuri Pankov } else
72c66b8046SYuri Pankov add = 0;
73c66b8046SYuri Pankov if (a2roffsu(arg, &su, SCALE_EM) == NULL)
74c66b8046SYuri Pankov return;
75c66b8046SYuri Pankov
76c66b8046SYuri Pankov /* Select the list, and extend it if it is full. */
77c66b8046SYuri Pankov
78c66b8046SYuri Pankov tl = recording_period ? &tabs.p : &tabs.a;
79c66b8046SYuri Pankov if (tl->n >= tl->s) {
80c66b8046SYuri Pankov tl->s += 8;
81c66b8046SYuri Pankov tl->t = mandoc_reallocarray(tl->t, tl->s, sizeof(*tl->t));
82c66b8046SYuri Pankov }
83c66b8046SYuri Pankov
84c66b8046SYuri Pankov /* Append the new position. */
85c66b8046SYuri Pankov
86c66b8046SYuri Pankov pos = term_hen(p, &su);
87c66b8046SYuri Pankov tl->t[tl->n] = pos;
88c66b8046SYuri Pankov if (add && tl->n)
89c66b8046SYuri Pankov tl->t[tl->n] += tl->t[tl->n - 1];
90c66b8046SYuri Pankov tl->n++;
91c66b8046SYuri Pankov }
92c66b8046SYuri Pankov
93c66b8046SYuri Pankov /*
94c66b8046SYuri Pankov * Simplified version without a parser,
95c66b8046SYuri Pankov * never incremental, never periodic, for use by tbl(7).
96c66b8046SYuri Pankov */
97c66b8046SYuri Pankov void
term_tab_iset(size_t inc)98c66b8046SYuri Pankov term_tab_iset(size_t inc)
99c66b8046SYuri Pankov {
100c66b8046SYuri Pankov if (tabs.a.n >= tabs.a.s) {
101c66b8046SYuri Pankov tabs.a.s += 8;
102c66b8046SYuri Pankov tabs.a.t = mandoc_reallocarray(tabs.a.t, tabs.a.s,
103c66b8046SYuri Pankov sizeof(*tabs.a.t));
104c66b8046SYuri Pankov }
105c66b8046SYuri Pankov tabs.a.t[tabs.a.n++] = inc;
106c66b8046SYuri Pankov }
107c66b8046SYuri Pankov
108c66b8046SYuri Pankov size_t
term_tab_next(size_t prev)109c66b8046SYuri Pankov term_tab_next(size_t prev)
110c66b8046SYuri Pankov {
111c66b8046SYuri Pankov size_t i, j;
112c66b8046SYuri Pankov
113c66b8046SYuri Pankov for (i = 0;; i++) {
114c66b8046SYuri Pankov if (i == tabs.a.n) {
115c66b8046SYuri Pankov if (tabs.p.n == 0)
116c66b8046SYuri Pankov return prev;
117c66b8046SYuri Pankov tabs.a.n += tabs.p.n;
118c66b8046SYuri Pankov if (tabs.a.s < tabs.a.n) {
119c66b8046SYuri Pankov tabs.a.s = tabs.a.n;
120c66b8046SYuri Pankov tabs.a.t = mandoc_reallocarray(tabs.a.t,
121c66b8046SYuri Pankov tabs.a.s, sizeof(*tabs.a.t));
122c66b8046SYuri Pankov }
123c66b8046SYuri Pankov for (j = 0; j < tabs.p.n; j++)
124c66b8046SYuri Pankov tabs.a.t[i + j] = tabs.p.t[j] +
125c66b8046SYuri Pankov (i ? tabs.a.t[i - 1] : 0);
126c66b8046SYuri Pankov }
127c66b8046SYuri Pankov if (prev < tabs.a.t[i])
128c66b8046SYuri Pankov return tabs.a.t[i];
129c66b8046SYuri Pankov }
130c66b8046SYuri Pankov }
131