1// -*- C++ -*-
2/* Copyright (C) 1989, 1990, 1991, 1992, 2002 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
21#include "eqn.h"
22#include "pbox.h"
23
24class limit_box : public box {
25private:
26  box *p;
27  box *from;
28  box *to;
29public:
30  limit_box(box *, box *, box *);
31  ~limit_box();
32  int compute_metrics(int);
33  void output();
34  void debug_print();
35  void check_tabs(int);
36};
37
38box *make_limit_box(box *pp, box *qq, box *rr)
39{
40  return new limit_box(pp, qq, rr);
41}
42
43limit_box::limit_box(box *pp, box *qq, box *rr)
44: p(pp), from(qq), to(rr)
45{
46  spacing_type = p->spacing_type;
47}
48
49limit_box::~limit_box()
50{
51  delete p;
52  delete from;
53  delete to;
54}
55
56int limit_box::compute_metrics(int style)
57{
58  printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
59  if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
60    set_script_size();
61  printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
62  int res = 0;
63  int mark_uid = -1;
64  if (from != 0) {
65    res = from->compute_metrics(cramped_style(script_style(style)));
66    if (res)
67      mark_uid = from->uid;
68  }
69  if (to != 0) {
70    int r = to->compute_metrics(script_style(style));
71    if (res && r)
72      error("multiple marks and lineups");
73    else  {
74      mark_uid = to->uid;
75      res = r;
76    }
77  }
78  printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
79  int r = p->compute_metrics(style);
80  p->compute_subscript_kern();
81  if (res && r)
82    error("multiple marks and lineups");
83  else {
84    mark_uid = p->uid;
85    res = r;
86  }
87  printf(".nr " LEFT_WIDTH_FORMAT " "
88	 "0\\n[" WIDTH_FORMAT "]",
89	 uid, p->uid);
90  if (from != 0)
91    printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
92	   p->uid, from->uid);
93  if (to != 0)
94    printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
95	   p->uid, to->uid);
96  printf("/2\n");
97  printf(".nr " WIDTH_FORMAT " "
98	 "0\\n[" WIDTH_FORMAT "]",
99	 uid, p->uid);
100  if (from != 0)
101    printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
102	   p->uid, from->uid);
103  if (to != 0)
104    printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
105	   p->uid, to->uid);
106  printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid);
107  printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
108  if (to != 0)
109    printf(">?\\n[" WIDTH_FORMAT "]", to->uid);
110  if (from != 0)
111    printf(">?\\n[" WIDTH_FORMAT "]", from->uid);
112  printf("\n");
113  if (res)
114    printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]"
115	   "-(\\n[" WIDTH_FORMAT "]/2))\n",
116	   uid, mark_uid);
117  if (to != 0) {
118    printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
119	   "]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
120	   uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid);
121    printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
122	   HEIGHT_FORMAT "]+%dM\n",
123	   uid, uid, to->uid, big_op_spacing5);
124  }
125  else
126    printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
127  if (from != 0) {
128    printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
129	   "]>?%dM+\\n[" DEPTH_FORMAT "]\n",
130	   uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid);
131    printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
132	   DEPTH_FORMAT "]+%dM\n",
133	   uid, uid, from->uid, big_op_spacing5);
134  }
135  else
136    printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
137  return res;
138}
139
140void limit_box::output()
141{
142  printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
143  if (to != 0) {
144    printf("\\Z" DELIMITER_CHAR);
145    printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
146    printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
147	   "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
148	   uid, to->uid, p->uid);
149    to->output();
150    printf(DELIMITER_CHAR);
151  }
152  if (from != 0) {
153    printf("\\Z" DELIMITER_CHAR);
154    printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
155    printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
156	   "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
157	   uid, p->uid, from->uid);
158    from->output();
159    printf(DELIMITER_CHAR);
160  }
161  printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
162  printf("\\Z" DELIMITER_CHAR);
163  printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
164	 "-(\\n[" WIDTH_FORMAT "]u/2u)'",
165	 uid, p->uid);
166  p->output();
167  printf(DELIMITER_CHAR);
168  printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
169}
170
171void limit_box::debug_print()
172{
173  fprintf(stderr, "{ ");
174  p->debug_print();
175  fprintf(stderr, " }");
176  if (from) {
177    fprintf(stderr, " from { ");
178    from->debug_print();
179    fprintf(stderr, " }");
180  }
181  if (to) {
182    fprintf(stderr, " to { ");
183    to->debug_print();
184    fprintf(stderr, " }");
185  }
186}
187
188void limit_box::check_tabs(int level)
189{
190  if (to)
191    to->check_tabs(level + 1);
192  if (from)
193    from->check_tabs(level + 1);
194  p->check_tabs(level + 1);
195}
196