1114402Sru// -*- C++ -*-
2114402Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2002 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
21114402Sru#include "eqn.h"
22114402Sru#include "pbox.h"
23114402Sru
24114402Sruclass limit_box : public box {
25114402Sruprivate:
26114402Sru  box *p;
27114402Sru  box *from;
28114402Sru  box *to;
29114402Srupublic:
30114402Sru  limit_box(box *, box *, box *);
31114402Sru  ~limit_box();
32114402Sru  int compute_metrics(int);
33114402Sru  void output();
34114402Sru  void debug_print();
35114402Sru  void check_tabs(int);
36114402Sru};
37114402Sru
38114402Srubox *make_limit_box(box *pp, box *qq, box *rr)
39114402Sru{
40114402Sru  return new limit_box(pp, qq, rr);
41114402Sru}
42114402Sru
43114402Srulimit_box::limit_box(box *pp, box *qq, box *rr)
44114402Sru: p(pp), from(qq), to(rr)
45114402Sru{
46114402Sru  spacing_type = p->spacing_type;
47114402Sru}
48114402Sru
49114402Srulimit_box::~limit_box()
50114402Sru{
51114402Sru  delete p;
52114402Sru  delete from;
53114402Sru  delete to;
54114402Sru}
55114402Sru
56114402Sruint limit_box::compute_metrics(int style)
57114402Sru{
58114402Sru  printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
59114402Sru  if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
60114402Sru    set_script_size();
61114402Sru  printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
62114402Sru  int res = 0;
63114402Sru  int mark_uid = -1;
64114402Sru  if (from != 0) {
65114402Sru    res = from->compute_metrics(cramped_style(script_style(style)));
66114402Sru    if (res)
67114402Sru      mark_uid = from->uid;
68114402Sru  }
69114402Sru  if (to != 0) {
70114402Sru    int r = to->compute_metrics(script_style(style));
71114402Sru    if (res && r)
72114402Sru      error("multiple marks and lineups");
73114402Sru    else  {
74114402Sru      mark_uid = to->uid;
75114402Sru      res = r;
76114402Sru    }
77114402Sru  }
78114402Sru  printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
79114402Sru  int r = p->compute_metrics(style);
80114402Sru  p->compute_subscript_kern();
81114402Sru  if (res && r)
82114402Sru    error("multiple marks and lineups");
83114402Sru  else {
84114402Sru    mark_uid = p->uid;
85114402Sru    res = r;
86114402Sru  }
87114402Sru  printf(".nr " LEFT_WIDTH_FORMAT " "
88114402Sru	 "0\\n[" WIDTH_FORMAT "]",
89114402Sru	 uid, p->uid);
90114402Sru  if (from != 0)
91114402Sru    printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
92114402Sru	   p->uid, from->uid);
93114402Sru  if (to != 0)
94114402Sru    printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
95114402Sru	   p->uid, to->uid);
96114402Sru  printf("/2\n");
97114402Sru  printf(".nr " WIDTH_FORMAT " "
98114402Sru	 "0\\n[" WIDTH_FORMAT "]",
99114402Sru	 uid, p->uid);
100114402Sru  if (from != 0)
101114402Sru    printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
102114402Sru	   p->uid, from->uid);
103114402Sru  if (to != 0)
104114402Sru    printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
105114402Sru	   p->uid, to->uid);
106114402Sru  printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid);
107114402Sru  printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
108114402Sru  if (to != 0)
109114402Sru    printf(">?\\n[" WIDTH_FORMAT "]", to->uid);
110114402Sru  if (from != 0)
111114402Sru    printf(">?\\n[" WIDTH_FORMAT "]", from->uid);
112114402Sru  printf("\n");
113114402Sru  if (res)
114114402Sru    printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]"
115114402Sru	   "-(\\n[" WIDTH_FORMAT "]/2))\n",
116114402Sru	   uid, mark_uid);
117114402Sru  if (to != 0) {
118114402Sru    printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
119114402Sru	   "]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
120114402Sru	   uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid);
121114402Sru    printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
122114402Sru	   HEIGHT_FORMAT "]+%dM\n",
123114402Sru	   uid, uid, to->uid, big_op_spacing5);
124114402Sru  }
125114402Sru  else
126114402Sru    printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
127114402Sru  if (from != 0) {
128114402Sru    printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
129114402Sru	   "]>?%dM+\\n[" DEPTH_FORMAT "]\n",
130114402Sru	   uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid);
131114402Sru    printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
132114402Sru	   DEPTH_FORMAT "]+%dM\n",
133114402Sru	   uid, uid, from->uid, big_op_spacing5);
134114402Sru  }
135114402Sru  else
136114402Sru    printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
137114402Sru  return res;
138114402Sru}
139114402Sru
140114402Sruvoid limit_box::output()
141114402Sru{
142114402Sru  printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
143114402Sru  if (to != 0) {
144114402Sru    printf("\\Z" DELIMITER_CHAR);
145114402Sru    printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
146114402Sru    printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
147114402Sru	   "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
148114402Sru	   uid, to->uid, p->uid);
149114402Sru    to->output();
150114402Sru    printf(DELIMITER_CHAR);
151114402Sru  }
152114402Sru  if (from != 0) {
153114402Sru    printf("\\Z" DELIMITER_CHAR);
154114402Sru    printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
155114402Sru    printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
156114402Sru	   "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
157114402Sru	   uid, p->uid, from->uid);
158114402Sru    from->output();
159114402Sru    printf(DELIMITER_CHAR);
160114402Sru  }
161114402Sru  printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
162114402Sru  printf("\\Z" DELIMITER_CHAR);
163114402Sru  printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
164114402Sru	 "-(\\n[" WIDTH_FORMAT "]u/2u)'",
165114402Sru	 uid, p->uid);
166114402Sru  p->output();
167114402Sru  printf(DELIMITER_CHAR);
168114402Sru  printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
169114402Sru}
170114402Sru
171114402Sruvoid limit_box::debug_print()
172114402Sru{
173114402Sru  fprintf(stderr, "{ ");
174114402Sru  p->debug_print();
175114402Sru  fprintf(stderr, " }");
176114402Sru  if (from) {
177114402Sru    fprintf(stderr, " from { ");
178114402Sru    from->debug_print();
179114402Sru    fprintf(stderr, " }");
180114402Sru  }
181114402Sru  if (to) {
182114402Sru    fprintf(stderr, " to { ");
183114402Sru    to->debug_print();
184114402Sru    fprintf(stderr, " }");
185114402Sru  }
186114402Sru}
187114402Sru
188114402Sruvoid limit_box::check_tabs(int level)
189114402Sru{
190114402Sru  if (to)
191114402Sru    to->check_tabs(level + 1);
192114402Sru  if (from)
193114402Sru    from->check_tabs(level + 1);
194114402Sru  p->check_tabs(level + 1);
195114402Sru}
196