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