1114402Sru// -*- C++ -*-
2151497Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
3114402Sru     Written by James Clark (jjc@jclark.com)
4114402Sru
5114402SruThis file is part of groff.
6114402Sru
7114402Srugroff is free software; you can redistribute it and/or modify it under
8114402Sruthe terms of the GNU General Public License as published by the Free
9114402SruSoftware Foundation; either version 2, or (at your option) any later
10114402Sruversion.
11114402Sru
12114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY
13114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
14114402SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15114402Srufor more details.
16114402Sru
17114402SruYou should have received a copy of the GNU General Public License along
18114402Sruwith groff; see the file COPYING.  If not, write to the Free Software
19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
20114402Sru// piles and matrices
21114402Sru
22114402Sru#include "eqn.h"
23114402Sru#include "pbox.h"
24114402Sru
25114402Sru// SUP_RAISE_FORMAT gives the first baseline
26114402Sru// BASELINE_SEP_FORMAT gives the separation between baselines
27114402Sru
28114402Sruint pile_box::compute_metrics(int style)
29114402Sru{
30114402Sru  int i;
31114402Sru  for (i = 0; i < col.len; i++)
32114402Sru    col.p[i]->compute_metrics(style);
33114402Sru  printf(".nr " WIDTH_FORMAT " 0", uid);
34114402Sru  for (i = 0; i < col.len; i++)
35114402Sru    printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
36114402Sru  printf("\n");
37114402Sru  printf(".nr " BASELINE_SEP_FORMAT " %dM",
38114402Sru	 uid, baseline_sep+col.space);
39114402Sru  for (i = 1; i < col.len; i++)
40114402Sru    printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
41114402Sru	   col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
42114402Sru  // round it so that it's a multiple of the vertical resolution
43114402Sru  printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
44114402Sru
45114402Sru  printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
46114402Sru	 "+%dM\n",
47114402Sru	 uid, uid, col.len-1, axis_height - shift_down);
48114402Sru  printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
49114402Sru	 HEIGHT_FORMAT "]\n",
50114402Sru	 uid, uid, col.p[0]->uid);
51114402Sru  printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
52114402Sru	 DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
53114402Sru	 uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
54114402Sru  return FOUND_NOTHING;
55114402Sru}
56114402Sru
57114402Sruvoid pile_box::output()
58114402Sru{
59114402Sru  int i;
60114402Sru  printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
61114402Sru  for (i = 0; i < col.len; i++) {
62114402Sru    switch (col.align) {
63114402Sru    case LEFT_ALIGN:
64114402Sru      break;
65114402Sru    case CENTER_ALIGN:
66114402Sru      printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
67114402Sru	     uid, col.p[i]->uid);
68114402Sru      break;
69114402Sru    case RIGHT_ALIGN:
70114402Sru      printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
71114402Sru	     uid, col.p[i]->uid);
72114402Sru      break;
73114402Sru    default:
74114402Sru      assert(0);
75114402Sru    }
76114402Sru    col.p[i]->output();
77114402Sru    printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
78114402Sru    switch (col.align) {
79114402Sru    case LEFT_ALIGN:
80114402Sru      break;
81114402Sru    case CENTER_ALIGN:
82114402Sru      printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
83114402Sru	     col.p[i]->uid, uid);
84114402Sru      break;
85114402Sru    case RIGHT_ALIGN:
86114402Sru      printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
87114402Sru	     col.p[i]->uid, uid);
88114402Sru      break;
89114402Sru    default:
90114402Sru      assert(0);
91114402Sru    }
92114402Sru    if (i != col.len - 1)
93114402Sru      printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
94114402Sru  }
95114402Sru  printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
96114402Sru  printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
97114402Sru  printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
98114402Sru}
99114402Sru
100114402Srupile_box::pile_box(box *pp) : col(pp)
101114402Sru{
102114402Sru}
103114402Sru
104114402Sruvoid pile_box::check_tabs(int level)
105114402Sru{
106114402Sru  col.list_check_tabs(level);
107114402Sru}
108114402Sru
109114402Sruvoid pile_box::debug_print()
110114402Sru{
111114402Sru  col.debug_print("pile");
112114402Sru}
113114402Sru
114114402Sruint matrix_box::compute_metrics(int style)
115114402Sru{
116114402Sru  int i, j;
117151497Sru  int max_len = 0;
118114402Sru  int space = 0;
119114402Sru  for (i = 0; i < len; i++) {
120114402Sru    for (j = 0; j < p[i]->len; j++)
121114402Sru      p[i]->p[j]->compute_metrics(style);
122151497Sru    if (p[i]->len > max_len)
123151497Sru      max_len = p[i]->len;
124114402Sru    if (p[i]->space > space)
125114402Sru      space = p[i]->space;
126114402Sru  }
127114402Sru  for (i = 0; i < len; i++) {
128114402Sru    printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
129114402Sru    for (j = 0; j < p[i]->len; j++)
130114402Sru      printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
131114402Sru    printf("\n");
132114402Sru  }
133114402Sru  printf(".nr " WIDTH_FORMAT " %dM",
134114402Sru	 uid, column_sep*(len-1)+2*matrix_side_sep);
135114402Sru  for (i = 0; i < len; i++)
136114402Sru    printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
137114402Sru  printf("\n");
138114402Sru  printf(".nr " BASELINE_SEP_FORMAT " %dM",
139114402Sru	 uid, baseline_sep+space);
140114402Sru  for (i = 0; i < len; i++)
141114402Sru    for (j = 1; j < p[i]->len; j++)
142114402Sru      printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
143114402Sru	   p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
144114402Sru  // round it so that it's a multiple of the vertical resolution
145114402Sru  printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
146114402Sru  printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
147114402Sru	 "+%dM\n",
148151497Sru	 uid, uid, max_len-1, axis_height - shift_down);
149114402Sru  printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
150114402Sru	 uid, uid);
151114402Sru  for (i = 0; i < len; i++)
152114402Sru    printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
153114402Sru  printf(")>?0\n");
154114402Sru  printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
155114402Sru	 SUP_RAISE_FORMAT "]+(0",
156151497Sru	 uid, uid, max_len-1, uid);
157114402Sru  for (i = 0; i < len; i++)
158151497Sru    if (p[i]->len == max_len)
159151497Sru      printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
160114402Sru  printf(")>?0\n");
161114402Sru  return FOUND_NOTHING;
162114402Sru}
163114402Sru
164114402Sruvoid matrix_box::output()
165114402Sru{
166114402Sru  printf("\\h'%dM'", matrix_side_sep);
167114402Sru  for (int i = 0; i < len; i++) {
168114402Sru    int j;
169114402Sru    printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
170114402Sru    for (j = 0; j < p[i]->len; j++) {
171114402Sru      switch (p[i]->align) {
172114402Sru      case LEFT_ALIGN:
173114402Sru	break;
174114402Sru      case CENTER_ALIGN:
175114402Sru	printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
176114402Sru	       uid, i, p[i]->p[j]->uid);
177114402Sru	break;
178114402Sru      case RIGHT_ALIGN:
179114402Sru	printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
180114402Sru	       uid, i, p[i]->p[j]->uid);
181114402Sru	break;
182114402Sru      default:
183114402Sru	assert(0);
184114402Sru      }
185114402Sru      p[i]->p[j]->output();
186114402Sru      printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
187114402Sru      switch (p[i]->align) {
188114402Sru      case LEFT_ALIGN:
189114402Sru	break;
190114402Sru      case CENTER_ALIGN:
191114402Sru	printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
192114402Sru	       p[i]->p[j]->uid, uid, i);
193114402Sru	break;
194114402Sru      case RIGHT_ALIGN:
195114402Sru	printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
196114402Sru	       p[i]->p[j]->uid, uid, i);
197114402Sru	break;
198114402Sru      default:
199114402Sru	assert(0);
200114402Sru      }
201114402Sru      if (j != p[i]->len - 1)
202114402Sru	printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
203114402Sru    }
204114402Sru    printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
205114402Sru    printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
206114402Sru    printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
207114402Sru    if (i != len - 1)
208114402Sru      printf("\\h'%dM'", column_sep);
209114402Sru  }
210114402Sru  printf("\\h'%dM'", matrix_side_sep);
211114402Sru}
212114402Sru
213114402Srumatrix_box::matrix_box(column *pp)
214114402Sru{
215114402Sru  p = new column*[10];
216114402Sru  for (int i = 0; i < 10; i++)
217114402Sru    p[i] = 0;
218114402Sru  maxlen = 10;
219114402Sru  len = 1;
220114402Sru  p[0] = pp;
221114402Sru}
222114402Sru
223114402Srumatrix_box::~matrix_box()
224114402Sru{
225114402Sru  for (int i = 0; i < len; i++)
226114402Sru    delete p[i];
227114402Sru  a_delete p;
228114402Sru}
229114402Sru
230114402Sruvoid matrix_box::append(column *pp)
231114402Sru{
232114402Sru  if (len + 1 > maxlen) {
233114402Sru    column **oldp = p;
234114402Sru    maxlen *= 2;
235114402Sru    p = new column*[maxlen];
236114402Sru    memcpy(p, oldp, sizeof(column*)*len);
237114402Sru    a_delete oldp;
238114402Sru  }
239114402Sru  p[len++] = pp;
240114402Sru}
241114402Sru
242114402Sruvoid matrix_box::check_tabs(int level)
243114402Sru{
244114402Sru  for (int i = 0; i < len; i++)
245114402Sru    p[i]->list_check_tabs(level);
246114402Sru}
247114402Sru
248114402Sruvoid matrix_box::debug_print()
249114402Sru{
250114402Sru  fprintf(stderr, "matrix { ");
251114402Sru  p[0]->debug_print("col");
252114402Sru  for (int i = 1; i < len; i++) {
253114402Sru    fprintf(stderr, " ");
254114402Sru    p[i]->debug_print("col");
255114402Sru  }
256114402Sru  fprintf(stderr, " }");
257114402Sru}
258114402Sru
259114402Srucolumn::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
260114402Sru{
261114402Sru}
262114402Sru
263114402Sruvoid column::set_alignment(alignment a)
264114402Sru{
265114402Sru  align = a;
266114402Sru}
267114402Sru
268114402Sruvoid column::set_space(int n)
269114402Sru{
270114402Sru  space = n;
271114402Sru}
272114402Sru
273114402Sruvoid column::debug_print(const char *s)
274114402Sru{
275114402Sru  char c = '\0';		// shut up -Wall
276114402Sru  switch (align) {
277114402Sru  case LEFT_ALIGN:
278114402Sru    c = 'l';
279114402Sru    break;
280114402Sru  case RIGHT_ALIGN:
281114402Sru    c = 'r';
282114402Sru    break;
283114402Sru  case CENTER_ALIGN:
284114402Sru    c = 'c';
285114402Sru    break;
286114402Sru  default:
287114402Sru    assert(0);
288114402Sru  }
289114402Sru  fprintf(stderr, "%c%s %d { ", c, s, space);
290114402Sru  list_debug_print(" above ");
291114402Sru  fprintf(stderr, " }");
292114402Sru}
293114402Sru
294