xref: /illumos-gate/usr/src/cmd/mandoc/term_tab.c (revision 4d131170)
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