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