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 over_box : public box {
27 : private:
28 : int reduce_size;
29 : box *num;
30 : box *den;
31 : public:
32 : over_box(int small, box *, box *);
33 : ~over_box();
34 : void debug_print();
35 : int compute_metrics(int);
36 : void output();
37 : void diagnose_tab_stop_usage(int);
38 : };
39 :
40 11 : box *make_over_box(box *pp, box *qq)
41 : {
42 11 : return new over_box(0, pp, qq);
43 : }
44 :
45 0 : box *make_small_over_box(box *pp, box *qq)
46 : {
47 0 : return new over_box(1, pp, qq);
48 : }
49 :
50 11 : over_box::over_box(int is_small, box *pp, box *qq)
51 11 : : reduce_size(is_small), num(pp), den(qq)
52 : {
53 11 : spacing_type = INNER_TYPE;
54 11 : }
55 :
56 22 : over_box::~over_box()
57 : {
58 11 : delete num;
59 11 : delete den;
60 22 : }
61 :
62 11 : int over_box::compute_metrics(int style)
63 : {
64 11 : if (reduce_size) {
65 0 : style = script_style(style);
66 0 : printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
67 0 : set_script_size();
68 0 : printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
69 : }
70 11 : int mark_uid = 0;
71 11 : int res = num->compute_metrics(style);
72 11 : if (res)
73 0 : mark_uid = num->uid;
74 11 : int r = den->compute_metrics(cramped_style(style));
75 11 : if (r && res)
76 0 : error("multiple marks and lineups");
77 : else {
78 11 : mark_uid = den->uid;
79 11 : res = r;
80 : }
81 11 : if (reduce_size)
82 0 : printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
83 11 : printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]",
84 11 : uid, num->uid, den->uid);
85 : // allow for \(ru being wider than both the numerator and denominator
86 11 : if (!draw_flag)
87 11 : fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout);
88 11 : printf(")+%dM\n", get_param("null_delimiter_space") * 2
89 11 : + get_param("over_hang") * 2);
90 : // 15b
91 22 : printf(".nr " SUP_RAISE_FORMAT " %dM\n",
92 11 : uid, (reduce_size ? get_param("num2") : get_param("num1")));
93 22 : printf(".nr " SUB_LOWER_FORMAT " %dM\n",
94 22 : uid, (reduce_size ? get_param("denom2")
95 11 : : get_param("denom1")));
96 :
97 : // 15d
98 11 : printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT
99 : "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n",
100 11 : uid, num->uid, uid, get_param("axis_height"),
101 : get_param("default_rule_thickness"),
102 11 : get_param("default_rule_thickness") * (reduce_size ? 1 : 3));
103 11 : printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT
104 : "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n",
105 11 : uid, den->uid, uid, get_param("axis_height"),
106 : get_param("default_rule_thickness"),
107 11 : get_param("default_rule_thickness") * (reduce_size ? 1 : 3));
108 :
109 :
110 11 : printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
111 : HEIGHT_FORMAT "]\n",
112 11 : uid, uid, num->uid);
113 11 : printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
114 : DEPTH_FORMAT "]\n",
115 11 : uid, uid, den->uid);
116 11 : if (res)
117 0 : printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n["
118 0 : WIDTH_FORMAT "]/2)\n", uid, mark_uid);
119 11 : return res;
120 : }
121 :
122 : #define USE_Z
123 :
124 11 : void over_box::output()
125 : {
126 11 : if (output_format == troff) {
127 11 : if (reduce_size)
128 0 : printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
129 : #ifdef USE_Z
130 11 : printf("\\Z" DELIMITER_CHAR);
131 : #endif
132 : // move up to the numerator baseline
133 11 : printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
134 : // move across so that it's centered
135 11 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
136 11 : uid, num->uid);
137 :
138 : // print the numerator
139 11 : num->output();
140 :
141 : #ifdef USE_Z
142 11 : printf(DELIMITER_CHAR);
143 : #else
144 : // back again
145 : printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid);
146 : printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
147 : uid, num->uid);
148 : // down again
149 : printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
150 : #endif
151 : #ifdef USE_Z
152 11 : printf("\\Z" DELIMITER_CHAR);
153 : #endif
154 : // move down to the denominator baseline
155 11 : printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
156 :
157 : // move across so that it's centered
158 11 : printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
159 11 : uid, den->uid);
160 :
161 : // print the denominator
162 11 : den->output();
163 :
164 : #ifdef USE_Z
165 11 : printf(DELIMITER_CHAR);
166 : #else
167 : // back again
168 : printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid);
169 : printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
170 : uid, den->uid);
171 : // up again
172 : printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid);
173 : #endif
174 11 : if (reduce_size)
175 0 : printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
176 : // draw the line
177 11 : printf("\\h'%dM'", get_param("null_delimiter_space"));
178 11 : printf("\\v'-%dM'", get_param("axis_height"));
179 11 : fputs(draw_flag ? "\\D'l" : "\\l'", stdout);
180 11 : printf("\\n[" WIDTH_FORMAT "]u-%dM",
181 11 : uid, 2 * get_param("null_delimiter_space"));
182 11 : fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout);
183 11 : printf("\\v'%dM'", get_param("axis_height"));
184 11 : printf("\\h'%dM'", get_param("null_delimiter_space"));
185 : }
186 0 : else if (output_format == mathml) {
187 : // FIXME: passing a displaystyle attribute doesn't validate.
188 0 : printf("<mfrac>");
189 0 : num->output();
190 0 : den->output();
191 0 : printf("</mfrac>");
192 : }
193 11 : }
194 :
195 0 : void over_box::debug_print()
196 : {
197 0 : fprintf(stderr, "{ ");
198 0 : num->debug_print();
199 0 : if (reduce_size)
200 0 : fprintf(stderr, " } smallover { ");
201 : else
202 0 : fprintf(stderr, " } over { ");
203 0 : den->debug_print();
204 0 : fprintf(stderr, " }");
205 0 : }
206 :
207 11 : void over_box::diagnose_tab_stop_usage(int level)
208 : {
209 11 : num->diagnose_tab_stop_usage(level + 1);
210 11 : den->diagnose_tab_stop_usage(level + 1);
211 11 : }
212 :
213 : // Local Variables:
214 : // fill-column: 72
215 : // mode: C++
216 : // End:
217 : // vim: set cindent noexpandtab shiftwidth=2 textwidth=72:
|