Commit | Line | Data |
---|---|---|
cad317cf C |
1 | // -*- C++ -*- |
2 | /* Copyright (C) 1989, 1990 Free Software Foundation, Inc. | |
3 | Written by James Clark (jjc@jclark.uucp) | |
4 | ||
5 | This file is part of groff. | |
6 | ||
7 | groff is free software; you can redistribute it and/or modify it under | |
8 | the terms of the GNU General Public License as published by the Free | |
9 | Software Foundation; either version 1, or (at your option) any later | |
10 | version. | |
11 | ||
12 | groff is distributed in the hope that it will be useful, but WITHOUT ANY | |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 | for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License along | |
18 | with groff; see the file LICENSE. If not, write to the Free Software | |
19 | Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | // piles and matrices | |
21 | ||
22 | #include "eqn.h" | |
23 | #include "pbox.h" | |
24 | ||
25 | // SUP_RAISE_FORMAT gives the first baseline | |
26 | // BASELINE_SEP_FORMAT gives the separation between baselines | |
27 | ||
28 | int pile_box::compute_metrics(int style) | |
29 | { | |
30 | int i; | |
31 | for (i = 0; i < col.len; i++) | |
32 | col.p[i]->compute_metrics(style); | |
33 | printf(".nr " WIDTH_FORMAT " 0", uid); | |
34 | for (i = 0; i < col.len; i++) | |
35 | printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid); | |
36 | printf("\n"); | |
37 | printf(".nr " BASELINE_SEP_FORMAT " %dM", | |
38 | uid, baseline_sep+col.space); | |
39 | for (i = 1; i < col.len; i++) | |
40 | printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", | |
41 | col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5); | |
42 | // round it so that it's a multiple of the vertical resolution | |
43 | printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); | |
44 | ||
45 | printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" | |
46 | "+%dM\n", | |
47 | uid, uid, col.len-1, axis_height - shift_down); | |
48 | printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" | |
49 | HEIGHT_FORMAT "]\n", | |
50 | uid, uid, col.p[0]->uid); | |
51 | printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n[" | |
52 | DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n", | |
53 | uid, uid, col.len-1, col.p[col.len-1]->uid, uid); | |
54 | return FOUND_NOTHING; | |
55 | } | |
56 | ||
57 | void pile_box::output() | |
58 | { | |
59 | int i; | |
60 | printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); | |
61 | for (i = 0; i < col.len; i++) { | |
62 | switch (col.align) { | |
63 | case LEFT_ALIGN: | |
64 | break; | |
65 | case CENTER_ALIGN: | |
66 | printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", | |
67 | uid, col.p[i]->uid); | |
68 | break; | |
69 | case RIGHT_ALIGN: | |
70 | printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", | |
71 | uid, col.p[i]->uid); | |
72 | break; | |
73 | default: | |
74 | assert(0); | |
75 | } | |
76 | col.p[i]->output(); | |
77 | printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid); | |
78 | switch (col.align) { | |
79 | case LEFT_ALIGN: | |
80 | break; | |
81 | case CENTER_ALIGN: | |
82 | printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", | |
83 | col.p[i]->uid, uid); | |
84 | break; | |
85 | case RIGHT_ALIGN: | |
86 | printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", | |
87 | col.p[i]->uid, uid); | |
88 | break; | |
89 | default: | |
90 | assert(0); | |
91 | } | |
92 | if (i != col.len - 1) | |
93 | printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); | |
94 | } | |
95 | printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); | |
96 | printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid); | |
97 | printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); | |
98 | } | |
99 | ||
100 | pile_box::pile_box(box *pp) : col(pp) | |
101 | { | |
102 | } | |
103 | ||
104 | void pile_box::check_tabs(int level) | |
105 | { | |
106 | col.list_check_tabs(level); | |
107 | } | |
108 | ||
109 | void pile_box::debug_print() | |
110 | { | |
111 | col.debug_print("pile"); | |
112 | } | |
113 | ||
114 | int matrix_box::compute_metrics(int style) | |
115 | { | |
116 | int i, j; | |
117 | int maxlen = 0; | |
118 | int space = 0; | |
119 | for (i = 0; i < len; i++) { | |
120 | for (j = 0; j < p[i]->len; j++) | |
121 | p[i]->p[j]->compute_metrics(style); | |
122 | if (p[i]->len > maxlen) | |
123 | maxlen = p[i]->len; | |
124 | if (p[i]->space > space) | |
125 | space = p[i]->space; | |
126 | } | |
127 | for (i = 0; i < len; i++) { | |
128 | printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i); | |
129 | for (j = 0; j < p[i]->len; j++) | |
130 | printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid); | |
131 | printf("\n"); | |
132 | } | |
133 | printf(".nr " WIDTH_FORMAT " %dM", | |
134 | uid, column_sep*(len-1)+2*matrix_side_sep); | |
135 | for (i = 0; i < len; i++) | |
136 | printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i); | |
137 | printf("\n"); | |
138 | printf(".nr " BASELINE_SEP_FORMAT " %dM", | |
139 | uid, baseline_sep+space); | |
140 | for (i = 0; i < len; i++) | |
141 | for (j = 1; j < p[i]->len; j++) | |
142 | printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", | |
143 | p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5); | |
144 | // round it so that it's a multiple of the vertical resolution | |
145 | printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); | |
146 | printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" | |
147 | "+%dM\n", | |
148 | uid, uid, maxlen-1, axis_height - shift_down); | |
149 | printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+(0", | |
150 | uid, uid); | |
151 | for (i = 0; i < len; i++) | |
152 | printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid); | |
153 | printf(")\n"); | |
154 | printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n[" | |
155 | SUP_RAISE_FORMAT "]+(0", | |
156 | uid, uid, maxlen-1, uid); | |
157 | for (i = 0; i < len; i++) | |
158 | if (p[i]->len == maxlen) | |
159 | printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[maxlen-1]->uid); | |
160 | printf(")\n"); | |
161 | return FOUND_NOTHING; | |
162 | } | |
163 | ||
164 | void matrix_box::output() | |
165 | { | |
166 | printf("\\h'%dM'", matrix_side_sep); | |
167 | for (int i = 0; i < len; i++) { | |
168 | int j; | |
169 | printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); | |
170 | for (j = 0; j < p[i]->len; j++) { | |
171 | switch (p[i]->align) { | |
172 | case LEFT_ALIGN: | |
173 | break; | |
174 | case CENTER_ALIGN: | |
175 | printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", | |
176 | uid, i, p[i]->p[j]->uid); | |
177 | break; | |
178 | case RIGHT_ALIGN: | |
179 | printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", | |
180 | uid, i, p[i]->p[j]->uid); | |
181 | break; | |
182 | default: | |
183 | assert(0); | |
184 | } | |
185 | p[i]->p[j]->output(); | |
186 | printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid); | |
187 | switch (p[i]->align) { | |
188 | case LEFT_ALIGN: | |
189 | break; | |
190 | case CENTER_ALIGN: | |
191 | printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'", | |
192 | p[i]->p[j]->uid, uid, i); | |
193 | break; | |
194 | case RIGHT_ALIGN: | |
195 | printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'", | |
196 | p[i]->p[j]->uid, uid, i); | |
197 | break; | |
198 | default: | |
199 | assert(0); | |
200 | } | |
201 | if (j != p[i]->len - 1) | |
202 | printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); | |
203 | } | |
204 | printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); | |
205 | printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid); | |
206 | printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i); | |
207 | if (i != len - 1) | |
208 | printf("\\h'%dM'", column_sep); | |
209 | } | |
210 | printf("\\h'%dM'", matrix_side_sep); | |
211 | } | |
212 | ||
213 | matrix_box::matrix_box(column *pp) | |
214 | { | |
215 | p = new column*[10]; | |
216 | for (int i = 0; i < 10; i++) | |
217 | p[i] = 0; | |
218 | maxlen = 10; | |
219 | len = 1; | |
220 | p[0] = pp; | |
221 | } | |
222 | ||
223 | matrix_box::~matrix_box() | |
224 | { | |
225 | for (int i = 0; i < len; i++) | |
226 | delete p[i]; | |
227 | delete p; | |
228 | } | |
229 | ||
230 | void matrix_box::append(column *pp) | |
231 | { | |
232 | if (len + 1 > maxlen) { | |
233 | column **oldp = p; | |
234 | maxlen *= 2; | |
235 | p = new column*[maxlen]; | |
236 | memcpy(p, oldp, sizeof(column*)*len); | |
237 | delete oldp; | |
238 | } | |
239 | p[len++] = pp; | |
240 | } | |
241 | ||
242 | void matrix_box::check_tabs(int level) | |
243 | { | |
244 | for (int i = 0; i < len; i++) | |
245 | p[i]->list_check_tabs(level); | |
246 | } | |
247 | ||
248 | void matrix_box::debug_print() | |
249 | { | |
250 | fprintf(stderr, "matrix { "); | |
251 | p[0]->debug_print("col"); | |
252 | for (int i = 1; i < len; i++) { | |
253 | fprintf(stderr, " "); | |
254 | p[i]->debug_print("col"); | |
255 | } | |
256 | fprintf(stderr, " }"); | |
257 | } | |
258 | ||
259 | column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0) | |
260 | { | |
261 | } | |
262 | ||
263 | void column::set_alignment(alignment a) | |
264 | { | |
265 | align = a; | |
266 | } | |
267 | ||
268 | void column::set_space(int n) | |
269 | { | |
270 | space = n; | |
271 | } | |
272 | ||
273 | void column::debug_print(const char *s) | |
274 | { | |
275 | char c = '\0'; // shut up -Wall | |
276 | switch (align) { | |
277 | case LEFT_ALIGN: | |
278 | c = 'l'; | |
279 | break; | |
280 | case RIGHT_ALIGN: | |
281 | c = 'r'; | |
282 | break; | |
283 | case CENTER_ALIGN: | |
284 | c = 'c'; | |
285 | break; | |
286 | default: | |
287 | assert(0); | |
288 | } | |
289 | fprintf(stderr, "%c%s %d { ", c, s, space); | |
290 | list_debug_print(" above "); | |
291 | fprintf(stderr, " }"); | |
292 | } | |
293 |