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