1// -*- C++ -*-
2/* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
3     Written by James Clark (jjc@jclark.com)
4
5This file is part of groff.
6
7groff is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12groff is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License along
18with groff; see the file COPYING.  If not, write to the Free Software
19Foundation, 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
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{
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
100pile_box::pile_box(box *pp) : col(pp)
101{
102}
103
104void pile_box::check_tabs(int level)
105{
106  col.list_check_tabs(level);
107}
108
109void pile_box::debug_print()
110{
111  col.debug_print("pile");
112}
113
114int 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
164void 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
213matrix_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
223matrix_box::~matrix_box()
224{
225  for (int i = 0; i < len; i++)
226    delete p[i];
227  a_delete p;
228}
229
230void 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
242void matrix_box::check_tabs(int level)
243{
244  for (int i = 0; i < len; i++)
245    p[i]->list_check_tabs(level);
246}
247
248void 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
259column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
260{
261}
262
263void column::set_alignment(alignment a)
264{
265  align = a;
266}
267
268void column::set_space(int n)
269{
270  space = n;
271}
272
273void 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
294