xref: /openbsd-src/usr.bin/mandoc/term_tab.c (revision 888caeec3c86c73e63b9ca3f81b39f468197aeec)
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