Adapt src/lib-snprintf (src/libs/snprintf)
[s-roff.git] / src / preproc / eqn / pile.cpp
blobe1fd6c1142a7e5c40322dff4bf0b527bd1ec92df
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2004, 2007
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
11 version.
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING. If not, write to the Free Software
20 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
21 // piles and matrices
23 #include "eqn.h"
24 #include "pbox.h"
26 // SUP_RAISE_FORMAT gives the first baseline
27 // BASELINE_SEP_FORMAT gives the separation between baselines
29 int pile_box::compute_metrics(int style)
31 int i;
32 for (i = 0; i < col.len; i++)
33 col.p[i]->compute_metrics(style);
34 printf(".nr " WIDTH_FORMAT " 0", uid);
35 for (i = 0; i < col.len; i++)
36 printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
37 printf("\n");
38 printf(".nr " BASELINE_SEP_FORMAT " %dM",
39 uid, baseline_sep+col.space);
40 for (i = 1; i < col.len; i++)
41 printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
42 col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
43 // round it so that it's a multiple of the vertical resolution
44 printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
46 printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
47 "+%dM\n",
48 uid, uid, col.len-1, axis_height - shift_down);
49 printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
50 HEIGHT_FORMAT "]\n",
51 uid, uid, col.p[0]->uid);
52 printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
53 DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
54 uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
55 return FOUND_NOTHING;
58 void pile_box::output()
60 if (output_format == troff) {
61 int i;
62 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
63 for (i = 0; i < col.len; i++) {
64 switch (col.align) {
65 case LEFT_ALIGN:
66 break;
67 case CENTER_ALIGN:
68 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
69 uid, col.p[i]->uid);
70 break;
71 case RIGHT_ALIGN:
72 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
73 uid, col.p[i]->uid);
74 break;
75 default:
76 assert(0);
78 col.p[i]->output();
79 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
80 switch (col.align) {
81 case LEFT_ALIGN:
82 break;
83 case CENTER_ALIGN:
84 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
85 col.p[i]->uid, uid);
86 break;
87 case RIGHT_ALIGN:
88 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
89 col.p[i]->uid, uid);
90 break;
91 default:
92 assert(0);
94 if (i != col.len - 1)
95 printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
97 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
98 printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
99 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
101 else if (output_format == mathml) {
102 const char *av;
103 switch (col.align) {
104 case LEFT_ALIGN:
105 av = "left";
106 break;
107 case RIGHT_ALIGN:
108 av = "right";
109 break;
110 case CENTER_ALIGN:
111 av = "center";
112 break;
113 default:
114 assert(0);
116 printf("<mtable columnalign='%s'>", av);
117 for (int i = 0; i < col.len; i++) {
118 printf("<mtr><mtd>");
119 col.p[i]->output();
120 printf("</mtd></mtr>");
122 printf("</mtable>");
126 pile_box::pile_box(box *pp) : col(pp)
130 void pile_box::check_tabs(int level)
132 col.list_check_tabs(level);
135 void pile_box::debug_print()
137 col.debug_print("pile");
140 int matrix_box::compute_metrics(int style)
142 int i, j;
143 int max_len = 0;
144 int space = 0;
145 for (i = 0; i < len; i++) {
146 for (j = 0; j < p[i]->len; j++)
147 p[i]->p[j]->compute_metrics(style);
148 if (p[i]->len > max_len)
149 max_len = p[i]->len;
150 if (p[i]->space > space)
151 space = p[i]->space;
153 for (i = 0; i < len; i++) {
154 printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
155 for (j = 0; j < p[i]->len; j++)
156 printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
157 printf("\n");
159 printf(".nr " WIDTH_FORMAT " %dM",
160 uid, column_sep*(len-1)+2*matrix_side_sep);
161 for (i = 0; i < len; i++)
162 printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
163 printf("\n");
164 printf(".nr " BASELINE_SEP_FORMAT " %dM",
165 uid, baseline_sep+space);
166 for (i = 0; i < len; i++)
167 for (j = 1; j < p[i]->len; j++)
168 printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
169 p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
170 // round it so that it's a multiple of the vertical resolution
171 printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
172 printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
173 "+%dM\n",
174 uid, uid, max_len-1, axis_height - shift_down);
175 printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
176 uid, uid);
177 for (i = 0; i < len; i++)
178 printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
179 printf(")>?0\n");
180 printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
181 SUP_RAISE_FORMAT "]+(0",
182 uid, uid, max_len-1, uid);
183 for (i = 0; i < len; i++)
184 if (p[i]->len == max_len)
185 printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
186 printf(")>?0\n");
187 return FOUND_NOTHING;
190 void matrix_box::output()
192 if (output_format == troff) {
193 printf("\\h'%dM'", matrix_side_sep);
194 for (int i = 0; i < len; i++) {
195 int j;
196 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
197 for (j = 0; j < p[i]->len; j++) {
198 switch (p[i]->align) {
199 case LEFT_ALIGN:
200 break;
201 case CENTER_ALIGN:
202 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
203 uid, i, p[i]->p[j]->uid);
204 break;
205 case RIGHT_ALIGN:
206 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
207 uid, i, p[i]->p[j]->uid);
208 break;
209 default:
210 assert(0);
212 p[i]->p[j]->output();
213 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
214 switch (p[i]->align) {
215 case LEFT_ALIGN:
216 break;
217 case CENTER_ALIGN:
218 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
219 p[i]->p[j]->uid, uid, i);
220 break;
221 case RIGHT_ALIGN:
222 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
223 p[i]->p[j]->uid, uid, i);
224 break;
225 default:
226 assert(0);
228 if (j != p[i]->len - 1)
229 printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
231 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
232 printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
233 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
234 if (i != len - 1)
235 printf("\\h'%dM'", column_sep);
237 printf("\\h'%dM'", matrix_side_sep);
239 else if (output_format == mathml) {
240 int n = p[0]->len; // Each column must have the same number of rows in it
241 printf("<mtable>");
242 for (int i = 0; i < n; i++) {
243 printf("<mtr>");
244 for (int j = 0; j < len; j++) {
245 const char *av;
246 switch (p[j]->align) {
247 case LEFT_ALIGN:
248 av = "left";
249 break;
250 case RIGHT_ALIGN:
251 av = "right";
252 break;
253 case CENTER_ALIGN:
254 av = "center";
255 break;
256 default:
257 assert(0);
259 printf("<mtd columnalign='%s'>", av);
260 p[j]->p[i]->output();
261 printf("</mtd>");
263 printf("</mtr>");
265 printf("</mtable>");
269 matrix_box::matrix_box(column *pp)
271 p = new column*[10];
272 for (int i = 0; i < 10; i++)
273 p[i] = 0;
274 maxlen = 10;
275 len = 1;
276 p[0] = pp;
279 matrix_box::~matrix_box()
281 for (int i = 0; i < len; i++)
282 delete p[i];
283 a_delete p;
286 void matrix_box::append(column *pp)
288 if (len + 1 > maxlen) {
289 column **oldp = p;
290 maxlen *= 2;
291 p = new column*[maxlen];
292 memcpy(p, oldp, sizeof(column*)*len);
293 a_delete oldp;
295 p[len++] = pp;
298 void matrix_box::check_tabs(int level)
300 for (int i = 0; i < len; i++)
301 p[i]->list_check_tabs(level);
304 void matrix_box::debug_print()
306 fprintf(stderr, "matrix { ");
307 p[0]->debug_print("col");
308 for (int i = 1; i < len; i++) {
309 fprintf(stderr, " ");
310 p[i]->debug_print("col");
312 fprintf(stderr, " }");
315 column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
319 void column::set_alignment(alignment a)
321 align = a;
324 void column::set_space(int n)
326 space = n;
329 void column::debug_print(const char *s)
331 char c = '\0'; // shut up -Wall
332 switch (align) {
333 case LEFT_ALIGN:
334 c = 'l';
335 break;
336 case RIGHT_ALIGN:
337 c = 'r';
338 break;
339 case CENTER_ALIGN:
340 c = 'c';
341 break;
342 default:
343 assert(0);
345 fprintf(stderr, "%c%s %d { ", c, s, space);
346 list_debug_print(" above ");
347 fprintf(stderr, " }");