CXX peace: src/pre-eqn/pile.cpp
[s-roff.git] / src / pre-eqn / pile.cpp
blobb675bb40d46157e02fa52afb8851147c358be3e3
1 /*@ piles and matrices.
3 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
5 * Copyright (C) 1989 - 1992, 2004, 2007
6 * Free Software Foundation, Inc.
7 * Written by James Clark (jjc@jclark.com)
9 * This is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2, or (at your option) any later
12 * version.
14 * This is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with groff; see the file COPYING. If not, write to the Free Software
21 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "config.h"
25 #include "eqn-config.h"
27 #include "eqn.h"
28 #include "pbox.h"
30 // SUP_RAISE_FORMAT gives the first baseline
31 // BASELINE_SEP_FORMAT gives the separation between baselines
33 int pile_box::compute_metrics(int style)
35 int i;
36 for (i = 0; i < col.len; i++)
37 col.p[i]->compute_metrics(style);
38 printf(".nr " WIDTH_FORMAT " 0", uid);
39 for (i = 0; i < col.len; i++)
40 printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
41 printf("\n");
42 printf(".nr " BASELINE_SEP_FORMAT " %dM",
43 uid, baseline_sep+col.space);
44 for (i = 1; i < col.len; i++)
45 printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
46 col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
47 // round it so that it's a multiple of the vertical resolution
48 printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
50 printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
51 "+%dM\n",
52 uid, uid, col.len-1, axis_height - shift_down);
53 printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
54 HEIGHT_FORMAT "]\n",
55 uid, uid, col.p[0]->uid);
56 printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
57 DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
58 uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
59 return FOUND_NOTHING;
62 void pile_box::output()
64 if (output_format == troff) {
65 int i;
66 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
67 for (i = 0; i < col.len; i++) {
68 switch (col.align) {
69 case LEFT_ALIGN:
70 break;
71 case CENTER_ALIGN:
72 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
73 uid, col.p[i]->uid);
74 break;
75 case RIGHT_ALIGN:
76 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
77 uid, col.p[i]->uid);
78 break;
79 default:
80 assert(0);
82 col.p[i]->output();
83 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
84 switch (col.align) {
85 case LEFT_ALIGN:
86 break;
87 case CENTER_ALIGN:
88 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
89 col.p[i]->uid, uid);
90 break;
91 case RIGHT_ALIGN:
92 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
93 col.p[i]->uid, uid);
94 break;
95 default:
96 assert(0);
98 if (i != col.len - 1)
99 printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
101 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
102 printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
103 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
105 else if (output_format == mathml) {
106 const char *av;
107 switch (col.align) {
108 case LEFT_ALIGN:
109 av = "left";
110 break;
111 case RIGHT_ALIGN:
112 av = "right";
113 break;
114 default:
115 assert(0);
116 // FALLTHRU (pacify compiler)
117 case CENTER_ALIGN:
118 av = "center";
119 break;
121 printf("<mtable columnalign='%s'>", av);
122 for (int i = 0; i < col.len; i++) {
123 printf("<mtr><mtd>");
124 col.p[i]->output();
125 printf("</mtd></mtr>");
127 printf("</mtable>");
131 pile_box::pile_box(box *pp) : col(pp)
135 void pile_box::check_tabs(int level)
137 col.list_check_tabs(level);
140 void pile_box::debug_print()
142 col.debug_print("pile");
145 int matrix_box::compute_metrics(int style)
147 int i, j;
148 int max_len = 0;
149 int space = 0;
150 for (i = 0; i < len; i++) {
151 for (j = 0; j < p[i]->len; j++)
152 p[i]->p[j]->compute_metrics(style);
153 if (p[i]->len > max_len)
154 max_len = p[i]->len;
155 if (p[i]->space > space)
156 space = p[i]->space;
158 for (i = 0; i < len; i++) {
159 printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
160 for (j = 0; j < p[i]->len; j++)
161 printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
162 printf("\n");
164 printf(".nr " WIDTH_FORMAT " %dM",
165 uid, column_sep*(len-1)+2*matrix_side_sep);
166 for (i = 0; i < len; i++)
167 printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
168 printf("\n");
169 printf(".nr " BASELINE_SEP_FORMAT " %dM",
170 uid, baseline_sep+space);
171 for (i = 0; i < len; i++)
172 for (j = 1; j < p[i]->len; j++)
173 printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
174 p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
175 // round it so that it's a multiple of the vertical resolution
176 printf("+(\\n(.V/2)/\\n(.V*\\n(.V\n");
177 printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
178 "+%dM\n",
179 uid, uid, max_len-1, axis_height - shift_down);
180 printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
181 uid, uid);
182 for (i = 0; i < len; i++)
183 printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
184 printf(")>?0\n");
185 printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
186 SUP_RAISE_FORMAT "]+(0",
187 uid, uid, max_len-1, uid);
188 for (i = 0; i < len; i++)
189 if (p[i]->len == max_len)
190 printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
191 printf(")>?0\n");
192 return FOUND_NOTHING;
195 void matrix_box::output()
197 if (output_format == troff) {
198 printf("\\h'%dM'", matrix_side_sep);
199 for (int i = 0; i < len; i++) {
200 int j;
201 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
202 for (j = 0; j < p[i]->len; j++) {
203 switch (p[i]->align) {
204 case LEFT_ALIGN:
205 break;
206 case CENTER_ALIGN:
207 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
208 uid, i, p[i]->p[j]->uid);
209 break;
210 case RIGHT_ALIGN:
211 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
212 uid, i, p[i]->p[j]->uid);
213 break;
214 default:
215 assert(0);
217 p[i]->p[j]->output();
218 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
219 switch (p[i]->align) {
220 case LEFT_ALIGN:
221 break;
222 case CENTER_ALIGN:
223 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
224 p[i]->p[j]->uid, uid, i);
225 break;
226 case RIGHT_ALIGN:
227 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
228 p[i]->p[j]->uid, uid, i);
229 break;
230 default:
231 assert(0);
233 if (j != p[i]->len - 1)
234 printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
236 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
237 printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
238 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
239 if (i != len - 1)
240 printf("\\h'%dM'", column_sep);
242 printf("\\h'%dM'", matrix_side_sep);
244 else if (output_format == mathml) {
245 int n = p[0]->len; // Each column must have the same number of rows in it
246 printf("<mtable>");
247 for (int i = 0; i < n; i++) {
248 printf("<mtr>");
249 for (int j = 0; j < len; j++) {
250 const char *av;
251 switch (p[j]->align) {
252 case LEFT_ALIGN:
253 av = "left";
254 break;
255 case RIGHT_ALIGN:
256 av = "right";
257 break;
258 default:
259 assert(0);
260 // FALLTHRU (pacify compiler)
261 case CENTER_ALIGN:
262 av = "center";
263 break;
265 printf("<mtd columnalign='%s'>", av);
266 p[j]->p[i]->output();
267 printf("</mtd>");
269 printf("</mtr>");
271 printf("</mtable>");
275 matrix_box::matrix_box(column *pp)
277 p = new column*[10];
278 for (int i = 0; i < 10; i++)
279 p[i] = 0;
280 maxlen = 10;
281 len = 1;
282 p[0] = pp;
285 matrix_box::~matrix_box()
287 for (int i = 0; i < len; i++)
288 delete p[i];
289 a_delete p;
292 void matrix_box::append(column *pp)
294 if (len + 1 > maxlen) {
295 column **oldp = p;
296 maxlen *= 2;
297 p = new column*[maxlen];
298 memcpy(p, oldp, sizeof(column*)*len);
299 a_delete oldp;
301 p[len++] = pp;
304 void matrix_box::check_tabs(int level)
306 for (int i = 0; i < len; i++)
307 p[i]->list_check_tabs(level);
310 void matrix_box::debug_print()
312 fprintf(stderr, "matrix { ");
313 p[0]->debug_print("col");
314 for (int i = 1; i < len; i++) {
315 fprintf(stderr, " ");
316 p[i]->debug_print("col");
318 fprintf(stderr, " }");
321 column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
325 void column::set_alignment(alignment a)
327 align = a;
330 void column::set_space(int n)
332 space = n;
335 void column::debug_print(const char *s)
337 char c = '\0'; // shut up -Wall
338 switch (align) {
339 case LEFT_ALIGN:
340 c = 'l';
341 break;
342 case RIGHT_ALIGN:
343 c = 'r';
344 break;
345 case CENTER_ALIGN:
346 c = 'c';
347 break;
348 default:
349 assert(0);
351 fprintf(stderr, "%c%s %d { ", c, s, space);
352 list_debug_print(" above ");
353 fprintf(stderr, " }");
356 // s-it2-mode