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