Adapt src/pre-eqn (src/preproc/eqn)
[s-roff.git] / src / pre-eqn / script.cpp
blobdad43ba0589fac5b84e0d218ed8253b0b5436f7a
1 /*@
2 * Copyright (c) 2014 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989 - 1992, 2002, 2004, 2007, 2008
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * groff is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
11 * version.
13 * groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "config.h"
24 #include "eqn-config.h"
26 #include "eqn.h"
27 #include "pbox.h"
29 class script_box
30 : public pointer_box
32 box *sub;
33 box *sup;
35 public:
36 script_box(box *, box *, box *);
37 ~script_box();
38 int compute_metrics(int);
39 void output();
40 void debug_print();
41 int left_is_italic();
42 void hint(unsigned);
43 void check_tabs(int);
46 /* The idea is that the script should attach to the rightmost box
47 of a list. For example, given `2x sup 3', the superscript should
48 attach to `x' rather than `2x'. */
50 box *make_script_box(box *nuc, box *sub, box *sup)
52 list_box *b = nuc->to_list_box();
53 if (b != 0) {
54 b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
55 sub,
56 sup);
57 return b;
59 else
60 return new script_box(nuc, sub, sup);
63 script_box::script_box(box *pp, box *qq, box *rr)
64 : pointer_box(pp), sub(qq), sup(rr)
68 script_box::~script_box()
70 delete sub;
71 delete sup;
74 int script_box::left_is_italic()
76 return p->left_is_italic();
79 int script_box::compute_metrics(int style)
81 int res = p->compute_metrics(style);
82 p->compute_subscript_kern();
83 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
84 if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
85 set_script_size();
86 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
87 if (sub != 0)
88 sub->compute_metrics(cramped_style(script_style(style)));
89 if (sup != 0)
90 sup->compute_metrics(script_style(style));
91 // 18a
92 if (p->is_char()) {
93 printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
94 printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
96 else {
97 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
98 uid, p->uid, sup_drop);
99 printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
100 uid, p->uid, sub_drop);
102 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
103 if (sup == 0) {
104 assert(sub != 0);
105 // 18b
106 printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
107 HEIGHT_FORMAT "]-(%dM*4/5))\n",
108 uid, uid, sub1, sub->uid, x_height);
110 else {
111 // sup != 0
112 // 18c
113 int pos;
114 if (style == DISPLAY_STYLE)
115 pos = sup1;
116 else if (style & 1) // not cramped
117 pos = sup2;
118 else
119 pos = sup3;
120 printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
121 "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
122 uid, uid, pos, sup->uid, x_height);
123 // 18d
124 if (sub != 0) {
125 printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
126 uid, uid, sub2);
127 // 18e
128 printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
129 SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
130 SUB_LOWER_FORMAT "]+(4*%dM)\n",
131 sup->uid, uid, sub->uid, uid, default_rule_thickness);
132 printf(".if \\n[" TEMP_REG "] \\{");
133 printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
134 printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
135 "]+\\n[" DEPTH_FORMAT "]>?0\n",
136 x_height, uid, sup->uid);
137 printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
138 printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
139 printf(".\\}\n");
142 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
143 if (sub != 0 && sup != 0)
144 printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
145 WIDTH_FORMAT "])+%dM)>?0\n",
146 sub->uid, p->uid, sup->uid, script_space);
147 else if (sub != 0)
148 printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
149 sub->uid, p->uid, script_space);
150 else if (sup != 0)
151 printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
152 else
153 printf("\n");
154 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
155 uid, p->uid);
156 if (sup != 0)
157 printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
158 uid, sup->uid);
159 if (sub != 0)
160 printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
161 uid, sub->uid);
162 printf("\n");
163 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
164 uid, p->uid);
165 if (sub != 0)
166 printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
167 uid, sub->uid);
168 if (sup != 0)
169 printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
170 uid, sup->uid);
171 printf("\n");
172 return res;
175 void script_box::output()
177 if (output_format == troff) {
178 p->output();
179 if (sup != 0) {
180 printf("\\Z" DELIMITER_CHAR);
181 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
182 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
183 sup->output();
184 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
185 printf(DELIMITER_CHAR);
187 if (sub != 0) {
188 printf("\\Z" DELIMITER_CHAR);
189 printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
190 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
191 printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
192 sub->output();
193 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
194 printf(DELIMITER_CHAR);
196 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
197 uid, p->uid);
199 else if (output_format == mathml) {
200 if (sup != 0 && sub != 0) {
201 printf("<msubsup>");
202 p->output();
203 sub->output();
204 sup->output();
205 printf("</msubsup>");
207 else if (sup != 0) {
208 printf("<msup>");
209 p->output();
210 sup->output();
211 printf("</msup>");
213 else if (sub != 0) {
214 printf("<msub>");
215 p->output();
216 sub->output();
217 printf("</msub>");
222 void script_box::hint(unsigned flags)
224 p->hint(flags & ~HINT_NEXT_IS_ITALIC);
227 void script_box::debug_print()
229 fprintf(stderr, "{ ");
230 p->debug_print();
231 fprintf(stderr, " }");
232 if (sub) {
233 fprintf(stderr, " sub { ");
234 sub->debug_print();
235 fprintf(stderr, " }");
237 if (sup) {
238 fprintf(stderr, " sup { ");
239 sup->debug_print();
240 fprintf(stderr, " }");
244 void script_box::check_tabs(int level)
246 if (sup)
247 sup->check_tabs(level + 1);
248 if (sub)
249 sub->check_tabs(level + 1);
250 p->check_tabs(level);
253 // s-it2-mode