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