Line data Source code
1 : /* Copyright 1989-2007 Free Software Foundation, Inc.
2 : Written by James Clark (jjc@jclark.com)
3 :
4 : This file is part of groff, the GNU roff typesetting system.
5 :
6 : groff is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : // piles and matrices
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include <config.h>
23 : #endif
24 :
25 : #include <assert.h>
26 :
27 : #include "eqn.h"
28 : #include "pbox.h"
29 :
30 : // SUP_RAISE_FORMAT gives the first baseline
31 : // BASELINE_SEP_FORMAT gives the separation between baselines
32 :
33 6 : int pile_box::compute_metrics(int style)
34 : {
35 : int i;
36 24 : for (i = 0; i < col.len; i++)
37 18 : col.p[i]->compute_metrics(style);
38 6 : printf(".nr " WIDTH_FORMAT " 0", uid);
39 24 : for (i = 0; i < col.len; i++)
40 18 : printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
41 6 : printf("\n");
42 6 : printf(".nr " BASELINE_SEP_FORMAT " %dM",
43 6 : uid, get_param("baseline_sep") + col.space);
44 18 : for (i = 1; i < col.len; i++)
45 12 : printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
46 12 : col.p[i-1]->uid, col.p[i]->uid,
47 12 : get_param("default_rule_thickness") * 5);
48 : // round it so that it's a multiple of the vertical motion quantum
49 6 : printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
50 :
51 6 : printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
52 : "+%dM\n",
53 6 : uid, uid, col.len-1, get_param("axis_height")
54 6 : - get_param("shift_down"));
55 6 : printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
56 : HEIGHT_FORMAT "]\n",
57 6 : uid, uid, col.p[0]->uid);
58 6 : printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
59 : DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
60 6 : uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
61 6 : return FOUND_NOTHING;
62 : }
63 :
64 6 : void pile_box::output()
65 : {
66 6 : if (output_format == troff) {
67 : int i;
68 6 : printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
69 24 : for (i = 0; i < col.len; i++) {
70 18 : switch (col.align) {
71 9 : case LEFT_ALIGN:
72 9 : break;
73 0 : case CENTER_ALIGN:
74 0 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
75 0 : uid, col.p[i]->uid);
76 0 : break;
77 9 : case RIGHT_ALIGN:
78 9 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
79 9 : uid, col.p[i]->uid);
80 9 : break;
81 0 : default:
82 0 : assert(0 == "unhandled case of column alignment");
83 : }
84 18 : col.p[i]->output();
85 18 : printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
86 18 : switch (col.align) {
87 9 : case LEFT_ALIGN:
88 9 : break;
89 0 : case CENTER_ALIGN:
90 0 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
91 0 : col.p[i]->uid, uid);
92 0 : break;
93 9 : case RIGHT_ALIGN:
94 9 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
95 9 : col.p[i]->uid, uid);
96 9 : break;
97 0 : default:
98 0 : assert(0 == "unhandled case of column alignment");
99 : }
100 18 : if (i != col.len - 1)
101 12 : printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
102 : }
103 6 : printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
104 6 : printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
105 6 : printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
106 : }
107 0 : else if (output_format == mathml) {
108 : const char *av;
109 0 : switch (col.align) {
110 0 : case LEFT_ALIGN:
111 0 : av = "left";
112 0 : break;
113 0 : case RIGHT_ALIGN:
114 0 : av = "right";
115 0 : break;
116 0 : case CENTER_ALIGN:
117 0 : av = "center";
118 0 : break;
119 0 : default:
120 0 : assert(0 == "unhandled case of column alignment");
121 : }
122 0 : printf("<mtable columnalign='%s'>", av);
123 0 : for (int i = 0; i < col.len; i++) {
124 0 : printf("<mtr><mtd>");
125 0 : col.p[i]->output();
126 0 : printf("</mtd></mtr>");
127 : }
128 0 : printf("</mtable>");
129 : }
130 6 : }
131 :
132 6 : pile_box::pile_box(box *pp) : col(pp)
133 : {
134 6 : }
135 :
136 6 : void pile_box::diagnose_tab_stop_usage(int level)
137 : {
138 6 : col.list_diagnose_tab_stop_usage(level);
139 6 : }
140 :
141 0 : void pile_box::debug_print()
142 : {
143 0 : col.debug_print("pile");
144 0 : }
145 :
146 0 : int matrix_box::compute_metrics(int style)
147 : {
148 : int i, j;
149 0 : int max_len = 0;
150 0 : int space = 0;
151 0 : for (i = 0; i < len; i++) {
152 0 : for (j = 0; j < p[i]->len; j++)
153 0 : p[i]->p[j]->compute_metrics(style);
154 0 : if (p[i]->len > max_len)
155 0 : max_len = p[i]->len;
156 0 : if (p[i]->space > space)
157 0 : space = p[i]->space;
158 : }
159 0 : for (i = 0; i < len; i++) {
160 0 : printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
161 0 : for (j = 0; j < p[i]->len; j++)
162 0 : printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
163 0 : printf("\n");
164 : }
165 0 : printf(".nr " WIDTH_FORMAT " %dM",
166 0 : uid, get_param("column_sep") * (len - 1) + 2
167 0 : * get_param("matrix_side_sep"));
168 0 : for (i = 0; i < len; i++)
169 0 : printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
170 0 : printf("\n");
171 0 : printf(".nr " BASELINE_SEP_FORMAT " %dM",
172 0 : uid, get_param("baseline_sep") + space);
173 0 : for (i = 0; i < len; i++)
174 0 : for (j = 1; j < p[i]->len; j++)
175 0 : printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
176 0 : p[i]->p[j-1]->uid, p[i]->p[j]->uid,
177 0 : get_param("default_rule_thickness") * 5);
178 : // round it so that it's a multiple of the vertical motion quantum
179 0 : printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
180 0 : printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
181 : "+%dM\n",
182 0 : uid, uid, max_len-1, get_param("axis_height")
183 0 : - get_param("shift_down"));
184 0 : printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
185 0 : uid, uid);
186 0 : for (i = 0; i < len; i++)
187 0 : printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
188 0 : printf(")>?0\n");
189 0 : printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
190 : SUP_RAISE_FORMAT "]+(0",
191 0 : uid, uid, max_len-1, uid);
192 0 : for (i = 0; i < len; i++)
193 0 : if (p[i]->len == max_len)
194 0 : printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
195 0 : printf(")>?0\n");
196 0 : return FOUND_NOTHING;
197 : }
198 :
199 0 : void matrix_box::output()
200 : {
201 0 : if (output_format == troff) {
202 0 : printf("\\h'%dM'", get_param("matrix_side_sep"));
203 0 : for (int i = 0; i < len; i++) {
204 : int j;
205 0 : printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
206 0 : for (j = 0; j < p[i]->len; j++) {
207 0 : switch (p[i]->align) {
208 0 : case LEFT_ALIGN:
209 0 : break;
210 0 : case CENTER_ALIGN:
211 0 : printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
212 0 : uid, i, p[i]->p[j]->uid);
213 0 : break;
214 0 : case RIGHT_ALIGN:
215 0 : printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
216 0 : uid, i, p[i]->p[j]->uid);
217 0 : break;
218 0 : default:
219 0 : assert(0 == "unhandled case of column alignment");
220 : }
221 0 : p[i]->p[j]->output();
222 0 : printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
223 0 : switch (p[i]->align) {
224 0 : case LEFT_ALIGN:
225 0 : break;
226 0 : case CENTER_ALIGN:
227 0 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
228 0 : p[i]->p[j]->uid, uid, i);
229 0 : break;
230 0 : case RIGHT_ALIGN:
231 0 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
232 0 : p[i]->p[j]->uid, uid, i);
233 0 : break;
234 0 : default:
235 0 : assert(0 == "unhandled case of column alignment");
236 : }
237 0 : if (j != p[i]->len - 1)
238 0 : printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
239 : }
240 0 : printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
241 0 : printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
242 0 : printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
243 0 : if (i != len - 1)
244 0 : printf("\\h'%dM'", get_param("column_sep"));
245 : }
246 0 : printf("\\h'%dM'", get_param("matrix_side_sep"));
247 : }
248 0 : else if (output_format == mathml) {
249 0 : int n = p[0]->len; // Each column must have the same number of rows in it
250 0 : printf("<mtable>");
251 0 : for (int i = 0; i < n; i++) {
252 0 : printf("<mtr>");
253 0 : for (int j = 0; j < len; j++) {
254 : const char *av;
255 0 : switch (p[j]->align) {
256 0 : case LEFT_ALIGN:
257 0 : av = "left";
258 0 : break;
259 0 : case RIGHT_ALIGN:
260 0 : av = "right";
261 0 : break;
262 0 : case CENTER_ALIGN:
263 0 : av = "center";
264 0 : break;
265 0 : default:
266 0 : assert(0 == "unhandled case of column alignment");
267 : }
268 0 : printf("<mtd columnalign='%s'>", av);
269 0 : p[j]->p[i]->output();
270 0 : printf("</mtd>");
271 : }
272 0 : printf("</mtr>");
273 : }
274 0 : printf("</mtable>");
275 : }
276 0 : }
277 :
278 0 : matrix_box::matrix_box(column *pp)
279 : {
280 0 : p = new column*[10];
281 0 : for (int i = 0; i < 10; i++)
282 0 : p[i] = 0;
283 0 : maxlen = 10;
284 0 : len = 1;
285 0 : p[0] = pp;
286 0 : }
287 :
288 0 : matrix_box::~matrix_box()
289 : {
290 0 : for (int i = 0; i < len; i++)
291 0 : delete p[i];
292 0 : delete[] p;
293 0 : }
294 :
295 0 : void matrix_box::append(column *pp)
296 : {
297 0 : if (len + 1 > maxlen) {
298 0 : column **oldp = p;
299 0 : maxlen *= 2;
300 0 : p = new column*[maxlen];
301 0 : memcpy(p, oldp, sizeof(column*)*len);
302 0 : delete[] oldp;
303 : }
304 0 : p[len++] = pp;
305 0 : }
306 :
307 0 : void matrix_box::diagnose_tab_stop_usage(int level)
308 : {
309 0 : for (int i = 0; i < len; i++)
310 0 : p[i]->list_diagnose_tab_stop_usage(level);
311 0 : }
312 :
313 0 : void matrix_box::debug_print()
314 : {
315 0 : fprintf(stderr, "matrix { ");
316 0 : p[0]->debug_print("col");
317 0 : for (int i = 1; i < len; i++) {
318 0 : fprintf(stderr, " ");
319 0 : p[i]->debug_print("col");
320 : }
321 0 : fprintf(stderr, " }");
322 0 : }
323 :
324 6 : column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
325 : {
326 6 : }
327 :
328 6 : void column::set_alignment(alignment a)
329 : {
330 6 : align = a;
331 6 : }
332 :
333 0 : void column::set_space(int n)
334 : {
335 0 : space = n;
336 0 : }
337 :
338 0 : void column::debug_print(const char *s)
339 : {
340 0 : char c = '\0'; // shut up -Wall
341 0 : switch (align) {
342 0 : case LEFT_ALIGN:
343 0 : c = 'l';
344 0 : break;
345 0 : case RIGHT_ALIGN:
346 0 : c = 'r';
347 0 : break;
348 0 : case CENTER_ALIGN:
349 0 : c = 'c';
350 0 : break;
351 0 : default:
352 0 : assert(0 == "unhandled case of column alignment");
353 : }
354 0 : fprintf(stderr, "%c%s %d { ", c, s, space);
355 0 : list_debug_print(" above ");
356 0 : fprintf(stderr, " }");
357 0 : }
358 :
359 : // Local Variables:
360 : // fill-column: 72
361 : // mode: C++
362 : // End:
363 : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:
|