Update to groff 1.19.2.
[dragonfly.git] / contrib / groff-1.19 / src / preproc / eqn / pile.cpp
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
3      Written by James Clark (jjc@jclark.com)
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 2, 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 COPYING.  If not, write to the Free Software
19 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, 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 max_len = 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 > max_len)
123       max_len = 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, max_len-1, axis_height - shift_down);
149   printf(".nr " HEIGHT_FORMAT " 0\\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(")>?0\n");
154   printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
155          SUP_RAISE_FORMAT "]+(0",
156          uid, uid, max_len-1, uid);
157   for (i = 0; i < len; i++)
158     if (p[i]->len == max_len)
159       printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
160   printf(")>?0\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   a_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     a_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