groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / preproc / eqn / limit.cpp
CommitLineData
92d0a6a6 1// -*- C++ -*-
4d3e9548
JL
2/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2007, 2009
3 Free Software Foundation, Inc.
92d0a6a6
JR
4 Written by James Clark (jjc@jclark.com)
5
6This file is part of groff.
7
8groff is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
4d3e9548
JL
10Software Foundation, either version 3 of the License, or
11(at your option) any later version.
92d0a6a6
JR
12
13groff is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
4d3e9548
JL
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>. */
92d0a6a6
JR
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{
4d3e9548
JL
142 if (output_format == troff) {
143 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
144 if (to != 0) {
145 printf("\\Z" DELIMITER_CHAR);
146 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
147 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
148 "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
149 uid, to->uid, p->uid);
150 to->output();
151 printf(DELIMITER_CHAR);
152 }
153 if (from != 0) {
154 printf("\\Z" DELIMITER_CHAR);
155 printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
156 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
157 "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
158 uid, p->uid, from->uid);
159 from->output();
160 printf(DELIMITER_CHAR);
161 }
162 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
92d0a6a6 163 printf("\\Z" DELIMITER_CHAR);
92d0a6a6 164 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
4d3e9548
JL
165 "-(\\n[" WIDTH_FORMAT "]u/2u)'",
166 uid, p->uid);
167 p->output();
92d0a6a6 168 printf(DELIMITER_CHAR);
4d3e9548 169 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
92d0a6a6 170 }
4d3e9548
JL
171 else if (output_format == mathml) {
172 if (from != 0 && to != 0) {
173 printf("<munderover>");
174 p->output();
175 from->output();
176 to->output();
177 printf("</munderover>");
178 }
179 else if (from != 0) {
180 printf("<munder>");
181 p->output();
182 from->output();
183 printf("</munder>");
184 }
185 else if (to != 0) {
186 printf("<mover>");
187 p->output();
188 to->output();
189 printf("</mover>");
190 }
92d0a6a6 191 }
92d0a6a6
JR
192}
193
194void limit_box::debug_print()
195{
196 fprintf(stderr, "{ ");
197 p->debug_print();
198 fprintf(stderr, " }");
199 if (from) {
200 fprintf(stderr, " from { ");
201 from->debug_print();
202 fprintf(stderr, " }");
203 }
204 if (to) {
205 fprintf(stderr, " to { ");
206 to->debug_print();
207 fprintf(stderr, " }");
208 }
209}
210
211void limit_box::check_tabs(int level)
212{
213 if (to)
214 to->check_tabs(level + 1);
215 if (from)
216 from->check_tabs(level + 1);
217 p->check_tabs(level + 1);
218}