Update to groff 1.19.2.
[dragonfly.git] / contrib / groff-1.19 / src / preproc / eqn / limit.cpp
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc.
3      Written by James Clark (jjc@jclark.com)
4
5 This file is part of groff.
6
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING.  If not, write to the Free Software
19 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
20
21 #include "eqn.h"
22 #include "pbox.h"
23
24 class limit_box : public box {
25 private:
26   box *p;
27   box *from;
28   box *to;
29 public:
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
38 box *make_limit_box(box *pp, box *qq, box *rr)
39 {
40   return new limit_box(pp, qq, rr);
41 }
42
43 limit_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
49 limit_box::~limit_box()
50 {
51   delete p;
52   delete from;
53   delete to;
54 }
55
56 int 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
140 void 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
171 void 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
188 void 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 }