Line data Source code
1 : /* Copyright 1989-2024 Free Software Foundation, Inc.
2 : Written by James Clark (jjc@jclark.com)
3 :
4 : This file is part of groff, the GNU roff typesetting system.
5 :
6 : groff is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation, either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : groff is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 :
19 : #ifdef HAVE_CONFIG_H
20 : #include <config.h>
21 : #endif
22 :
23 : #include "eqn.h"
24 : #include "pbox.h"
25 :
26 : class limit_box : public box {
27 : private:
28 : box *p;
29 : box *from;
30 : box *to;
31 : public:
32 : limit_box(box *, box *, box *);
33 : ~limit_box();
34 : int compute_metrics(int);
35 : void output();
36 : void debug_print();
37 : void diagnose_tab_stop_usage(int);
38 : };
39 :
40 16 : box *make_limit_box(box *pp, box *qq, box *rr)
41 : {
42 16 : return new limit_box(pp, qq, rr);
43 : }
44 :
45 16 : limit_box::limit_box(box *pp, box *qq, box *rr)
46 16 : : p(pp), from(qq), to(rr)
47 : {
48 16 : spacing_type = p->spacing_type;
49 16 : }
50 :
51 32 : limit_box::~limit_box()
52 : {
53 16 : delete p;
54 16 : delete from;
55 16 : delete to;
56 32 : }
57 :
58 16 : int limit_box::compute_metrics(int style)
59 : {
60 16 : printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
61 16 : if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
62 16 : set_script_size();
63 16 : printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
64 16 : int res = 0;
65 16 : int mark_uid = -1;
66 16 : if (from != 0) {
67 16 : res = from->compute_metrics(cramped_style(script_style(style)));
68 16 : if (res)
69 0 : mark_uid = from->uid;
70 : }
71 16 : if (to != 0) {
72 16 : int r = to->compute_metrics(script_style(style));
73 16 : if (res && r)
74 0 : error("multiple marks and lineups");
75 : else {
76 16 : mark_uid = to->uid;
77 16 : res = r;
78 : }
79 : }
80 16 : printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
81 16 : int r = p->compute_metrics(style);
82 16 : p->compute_subscript_kern();
83 16 : if (res && r)
84 0 : error("multiple marks and lineups");
85 : else {
86 16 : mark_uid = p->uid;
87 16 : res = r;
88 : }
89 16 : printf(".nr " LEFT_WIDTH_FORMAT " "
90 : "0\\n[" WIDTH_FORMAT "]",
91 16 : uid, p->uid);
92 16 : if (from != 0)
93 16 : printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
94 16 : p->uid, from->uid);
95 16 : if (to != 0)
96 16 : printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
97 16 : p->uid, to->uid);
98 16 : printf("/2\n");
99 16 : printf(".nr " WIDTH_FORMAT " "
100 : "0\\n[" WIDTH_FORMAT "]",
101 16 : uid, p->uid);
102 16 : if (from != 0)
103 16 : printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
104 16 : p->uid, from->uid);
105 16 : if (to != 0)
106 16 : printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
107 16 : p->uid, to->uid);
108 16 : printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid);
109 16 : printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
110 16 : if (to != 0)
111 16 : printf(">?\\n[" WIDTH_FORMAT "]", to->uid);
112 16 : if (from != 0)
113 16 : printf(">?\\n[" WIDTH_FORMAT "]", from->uid);
114 16 : printf("\n");
115 16 : if (res)
116 0 : printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]"
117 : "-(\\n[" WIDTH_FORMAT "]/2))\n",
118 0 : uid, mark_uid);
119 16 : if (to != 0) {
120 48 : printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
121 : "]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
122 16 : uid, get_param("big_op_spacing1"), to->uid,
123 16 : get_param("big_op_spacing3"), p->uid);
124 16 : printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
125 : HEIGHT_FORMAT "]+%dM\n",
126 16 : uid, uid, to->uid, get_param("big_op_spacing5"));
127 : }
128 : else
129 0 : printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
130 16 : if (from != 0) {
131 48 : printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
132 : "]>?%dM+\\n[" DEPTH_FORMAT "]\n",
133 16 : uid, get_param("big_op_spacing2"), from->uid,
134 16 : get_param("big_op_spacing4"), p->uid);
135 16 : printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
136 : DEPTH_FORMAT "]+%dM\n",
137 16 : uid, uid, from->uid, get_param("big_op_spacing5"));
138 : }
139 : else
140 0 : printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
141 16 : return res;
142 : }
143 :
144 16 : void limit_box::output()
145 : {
146 16 : if (output_format == troff) {
147 16 : printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
148 16 : if (to != 0) {
149 16 : printf("\\Z" DELIMITER_CHAR);
150 16 : printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
151 16 : printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
152 : "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
153 16 : uid, to->uid, p->uid);
154 16 : to->output();
155 16 : printf(DELIMITER_CHAR);
156 : }
157 16 : if (from != 0) {
158 16 : printf("\\Z" DELIMITER_CHAR);
159 16 : printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
160 16 : printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
161 : "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
162 16 : uid, p->uid, from->uid);
163 16 : from->output();
164 16 : printf(DELIMITER_CHAR);
165 : }
166 16 : printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
167 16 : printf("\\Z" DELIMITER_CHAR);
168 16 : printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
169 : "-(\\n[" WIDTH_FORMAT "]u/2u)'",
170 16 : uid, p->uid);
171 16 : p->output();
172 16 : printf(DELIMITER_CHAR);
173 16 : printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
174 : }
175 0 : else if (output_format == mathml) {
176 0 : if (from != 0 && to != 0) {
177 0 : printf("<munderover>");
178 0 : p->output();
179 0 : from->output();
180 0 : to->output();
181 0 : printf("</munderover>");
182 : }
183 0 : else if (from != 0) {
184 0 : printf("<munder>");
185 0 : p->output();
186 0 : from->output();
187 0 : printf("</munder>");
188 : }
189 0 : else if (to != 0) {
190 0 : printf("<mover>");
191 0 : p->output();
192 0 : to->output();
193 0 : printf("</mover>");
194 : }
195 : }
196 16 : }
197 :
198 0 : void limit_box::debug_print()
199 : {
200 0 : fprintf(stderr, "{ ");
201 0 : p->debug_print();
202 0 : fprintf(stderr, " }");
203 0 : if (from) {
204 0 : fprintf(stderr, " from { ");
205 0 : from->debug_print();
206 0 : fprintf(stderr, " }");
207 : }
208 0 : if (to) {
209 0 : fprintf(stderr, " to { ");
210 0 : to->debug_print();
211 0 : fprintf(stderr, " }");
212 : }
213 0 : }
214 :
215 16 : void limit_box::diagnose_tab_stop_usage(int level)
216 : {
217 16 : if (to)
218 16 : to->diagnose_tab_stop_usage(level + 1);
219 16 : if (from)
220 16 : from->diagnose_tab_stop_usage(level + 1);
221 16 : p->diagnose_tab_stop_usage(level + 1);
222 16 : }
223 :
224 : // Local Variables:
225 : // fill-column: 72
226 : // mode: C++
227 : // End:
228 : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:
|