groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / preproc / eqn / script.cpp
CommitLineData
92d0a6a6 1// -*- C++ -*-
4d3e9548 2/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004, 2007, 2008, 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 script_box : public pointer_box {
25private:
26 box *sub;
27 box *sup;
28public:
29 script_box(box *, box *, box *);
30 ~script_box();
31 int compute_metrics(int);
32 void output();
33 void debug_print();
34 int left_is_italic();
35 void hint(unsigned);
36 void check_tabs(int);
37};
38
39/* The idea is that the script should attach to the rightmost box
40of a list. For example, given `2x sup 3', the superscript should
41attach to `x' rather than `2x'. */
42
43box *make_script_box(box *nuc, box *sub, box *sup)
44{
45 list_box *b = nuc->to_list_box();
46 if (b != 0) {
47 b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
48 sub,
49 sup);
50 return b;
51 }
52 else
53 return new script_box(nuc, sub, sup);
54}
55
56script_box::script_box(box *pp, box *qq, box *rr)
57: pointer_box(pp), sub(qq), sup(rr)
58{
59}
60
61script_box::~script_box()
62{
63 delete sub;
64 delete sup;
65}
66
67int script_box::left_is_italic()
68{
69 return p->left_is_italic();
70}
71
72int script_box::compute_metrics(int style)
73{
74 int res = p->compute_metrics(style);
75 p->compute_subscript_kern();
76 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
77 if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
78 set_script_size();
79 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
80 if (sub != 0)
81 sub->compute_metrics(cramped_style(script_style(style)));
82 if (sup != 0)
83 sup->compute_metrics(script_style(style));
84 // 18a
85 if (p->is_char()) {
86 printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
87 printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
88 }
89 else {
90 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
91 uid, p->uid, sup_drop);
92 printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
93 uid, p->uid, sub_drop);
94 }
95 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
96 if (sup == 0) {
97 assert(sub != 0);
98 // 18b
99 printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
100 HEIGHT_FORMAT "]-(%dM*4/5))\n",
101 uid, uid, sub1, sub->uid, x_height);
102 }
103 else {
104 // sup != 0
105 // 18c
106 int pos;
107 if (style == DISPLAY_STYLE)
108 pos = sup1;
109 else if (style & 1) // not cramped
110 pos = sup2;
111 else
112 pos = sup3;
113 printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
114 "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
115 uid, uid, pos, sup->uid, x_height);
116 // 18d
117 if (sub != 0) {
118 printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
119 uid, uid, sub2);
120 // 18e
121 printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
122 SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
123 SUB_LOWER_FORMAT "]+(4*%dM)\n",
124 sup->uid, uid, sub->uid, uid, default_rule_thickness);
125 printf(".if \\n[" TEMP_REG "] \\{");
126 printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
127 printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
128 "]+\\n[" DEPTH_FORMAT "]>?0\n",
129 x_height, uid, sup->uid);
130 printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
131 printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
132 printf(".\\}\n");
133 }
134 }
135 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
136 if (sub != 0 && sup != 0)
137 printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
138 WIDTH_FORMAT "])+%dM)>?0\n",
139 sub->uid, p->uid, sup->uid, script_space);
140 else if (sub != 0)
141 printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
142 sub->uid, p->uid, script_space);
143 else if (sup != 0)
144 printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
145 else
146 printf("\n");
147 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
148 uid, p->uid);
149 if (sup != 0)
150 printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
151 uid, sup->uid);
152 if (sub != 0)
153 printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
154 uid, sub->uid);
155 printf("\n");
156 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
157 uid, p->uid);
158 if (sub != 0)
159 printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
160 uid, sub->uid);
161 if (sup != 0)
162 printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
163 uid, sup->uid);
164 printf("\n");
165 return res;
166}
167
168void script_box::output()
169{
4d3e9548
JL
170 if (output_format == troff) {
171 p->output();
172 if (sup != 0) {
173 printf("\\Z" DELIMITER_CHAR);
174 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
175 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
176 sup->output();
177 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
178 printf(DELIMITER_CHAR);
179 }
180 if (sub != 0) {
181 printf("\\Z" DELIMITER_CHAR);
182 printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
183 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
184 printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
185 sub->output();
186 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
187 printf(DELIMITER_CHAR);
188 }
189 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
190 uid, p->uid);
92d0a6a6 191 }
4d3e9548
JL
192 else if (output_format == mathml) {
193 if (sup != 0 && sub != 0) {
194 printf("<msubsup>");
195 p->output();
196 sub->output();
197 sup->output();
198 printf("</msubsup>");
199 }
200 else if (sup != 0) {
201 printf("<msup>");
202 p->output();
203 sup->output();
204 printf("</msup>");
205 }
206 else if (sub != 0) {
207 printf("<msub>");
208 p->output();
209 sub->output();
210 printf("</msub>");
211 }
92d0a6a6 212 }
92d0a6a6
JR
213}
214
215void script_box::hint(unsigned flags)
216{
217 p->hint(flags & ~HINT_NEXT_IS_ITALIC);
218}
219
220void script_box::debug_print()
221{
222 fprintf(stderr, "{ ");
223 p->debug_print();
224 fprintf(stderr, " }");
225 if (sub) {
226 fprintf(stderr, " sub { ");
227 sub->debug_print();
228 fprintf(stderr, " }");
229 }
230 if (sup) {
231 fprintf(stderr, " sup { ");
232 sup->debug_print();
233 fprintf(stderr, " }");
234 }
235}
236
237void script_box::check_tabs(int level)
238{
239 if (sup)
240 sup->check_tabs(level + 1);
241 if (sub)
242 sub->check_tabs(level + 1);
243 p->check_tabs(level);
244}