1/*	$NetBSD: pile.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $	*/
2
3// -*- C++ -*-
4/* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc.
5     Written by James Clark (jjc@jclark.com)
6
7This file is part of groff.
8
9groff is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 2, or (at your option) any later
12version.
13
14groff is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License along
20with groff; see the file COPYING.  If not, write to the Free Software
21Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
22// piles and matrices
23
24#include "eqn.h"
25#include "pbox.h"
26
27// SUP_RAISE_FORMAT gives the first baseline
28// BASELINE_SEP_FORMAT gives the separation between baselines
29
30int pile_box::compute_metrics(int style)
31{
32  int i;
33  for (i = 0; i < col.len; i++)
34    col.p[i]->compute_metrics(style);
35  printf(".nr " WIDTH_FORMAT " 0", uid);
36  for (i = 0; i < col.len; i++)
37    printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
38  printf("\n");
39  printf(".nr " BASELINE_SEP_FORMAT " %dM",
40	 uid, baseline_sep+col.space);
41  for (i = 1; i < col.len; i++)
42    printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
43	   col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
44  // round it so that it's a multiple of the vertical resolution
45  printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
46
47  printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
48	 "+%dM\n",
49	 uid, uid, col.len-1, axis_height - shift_down);
50  printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
51	 HEIGHT_FORMAT "]\n",
52	 uid, uid, col.p[0]->uid);
53  printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
54	 DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
55	 uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
56  return FOUND_NOTHING;
57}
58
59void pile_box::output()
60{
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);
77    }
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);
93    }
94    if (i != col.len - 1)
95      printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
96  }
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);
100}
101
102pile_box::pile_box(box *pp) : col(pp)
103{
104}
105
106void pile_box::check_tabs(int level)
107{
108  col.list_check_tabs(level);
109}
110
111void pile_box::debug_print()
112{
113  col.debug_print("pile");
114}
115
116int matrix_box::compute_metrics(int style)
117{
118  int i, j;
119  int max_len = 0;
120  int space = 0;
121  for (i = 0; i < len; i++) {
122    for (j = 0; j < p[i]->len; j++)
123      p[i]->p[j]->compute_metrics(style);
124    if (p[i]->len > max_len)
125      max_len = p[i]->len;
126    if (p[i]->space > space)
127      space = p[i]->space;
128  }
129  for (i = 0; i < len; i++) {
130    printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
131    for (j = 0; j < p[i]->len; j++)
132      printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
133    printf("\n");
134  }
135  printf(".nr " WIDTH_FORMAT " %dM",
136	 uid, column_sep*(len-1)+2*matrix_side_sep);
137  for (i = 0; i < len; i++)
138    printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
139  printf("\n");
140  printf(".nr " BASELINE_SEP_FORMAT " %dM",
141	 uid, baseline_sep+space);
142  for (i = 0; i < len; i++)
143    for (j = 1; j < p[i]->len; j++)
144      printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
145	   p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
146  // round it so that it's a multiple of the vertical resolution
147  printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
148  printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
149	 "+%dM\n",
150	 uid, uid, max_len-1, axis_height - shift_down);
151  printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0",
152	 uid, uid);
153  for (i = 0; i < len; i++)
154    printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
155  printf(")>?0\n");
156  printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
157	 SUP_RAISE_FORMAT "]+(0",
158	 uid, uid, max_len-1, uid);
159  for (i = 0; i < len; i++)
160    if (p[i]->len == max_len)
161      printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid);
162  printf(")>?0\n");
163  return FOUND_NOTHING;
164}
165
166void matrix_box::output()
167{
168  printf("\\h'%dM'", matrix_side_sep);
169  for (int i = 0; i < len; i++) {
170    int j;
171    printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
172    for (j = 0; j < p[i]->len; j++) {
173      switch (p[i]->align) {
174      case LEFT_ALIGN:
175	break;
176      case CENTER_ALIGN:
177	printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
178	       uid, i, p[i]->p[j]->uid);
179	break;
180      case RIGHT_ALIGN:
181	printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
182	       uid, i, p[i]->p[j]->uid);
183	break;
184      default:
185	assert(0);
186      }
187      p[i]->p[j]->output();
188      printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
189      switch (p[i]->align) {
190      case LEFT_ALIGN:
191	break;
192      case CENTER_ALIGN:
193	printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
194	       p[i]->p[j]->uid, uid, i);
195	break;
196      case RIGHT_ALIGN:
197	printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
198	       p[i]->p[j]->uid, uid, i);
199	break;
200      default:
201	assert(0);
202      }
203      if (j != p[i]->len - 1)
204	printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
205    }
206    printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
207    printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
208    printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
209    if (i != len - 1)
210      printf("\\h'%dM'", column_sep);
211  }
212  printf("\\h'%dM'", matrix_side_sep);
213}
214
215matrix_box::matrix_box(column *pp)
216{
217  p = new column*[10];
218  for (int i = 0; i < 10; i++)
219    p[i] = 0;
220  maxlen = 10;
221  len = 1;
222  p[0] = pp;
223}
224
225matrix_box::~matrix_box()
226{
227  for (int i = 0; i < len; i++)
228    delete p[i];
229  a_delete p;
230}
231
232void matrix_box::append(column *pp)
233{
234  if (len + 1 > maxlen) {
235    column **oldp = p;
236    maxlen *= 2;
237    p = new column*[maxlen];
238    memcpy(p, oldp, sizeof(column*)*len);
239    a_delete oldp;
240  }
241  p[len++] = pp;
242}
243
244void matrix_box::check_tabs(int level)
245{
246  for (int i = 0; i < len; i++)
247    p[i]->list_check_tabs(level);
248}
249
250void matrix_box::debug_print()
251{
252  fprintf(stderr, "matrix { ");
253  p[0]->debug_print("col");
254  for (int i = 1; i < len; i++) {
255    fprintf(stderr, " ");
256    p[i]->debug_print("col");
257  }
258  fprintf(stderr, " }");
259}
260
261column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
262{
263}
264
265void column::set_alignment(alignment a)
266{
267  align = a;
268}
269
270void column::set_space(int n)
271{
272  space = n;
273}
274
275void column::debug_print(const char *s)
276{
277  char c = '\0';		// shut up -Wall
278  switch (align) {
279  case LEFT_ALIGN:
280    c = 'l';
281    break;
282  case RIGHT_ALIGN:
283    c = 'r';
284    break;
285  case CENTER_ALIGN:
286    c = 'c';
287    break;
288  default:
289    assert(0);
290  }
291  fprintf(stderr, "%c%s %d { ", c, s, space);
292  list_debug_print(" above ");
293  fprintf(stderr, " }");
294}
295
296