1*89a07cf8Schristos /* $NetBSD: script.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */
2*89a07cf8Schristos
3*89a07cf8Schristos // -*- C++ -*-
4*89a07cf8Schristos /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004
5*89a07cf8Schristos Free Software Foundation, Inc.
6*89a07cf8Schristos Written by James Clark (jjc@jclark.com)
7*89a07cf8Schristos
8*89a07cf8Schristos This file is part of groff.
9*89a07cf8Schristos
10*89a07cf8Schristos groff is free software; you can redistribute it and/or modify it under
11*89a07cf8Schristos the terms of the GNU General Public License as published by the Free
12*89a07cf8Schristos Software Foundation; either version 2, or (at your option) any later
13*89a07cf8Schristos version.
14*89a07cf8Schristos
15*89a07cf8Schristos groff is distributed in the hope that it will be useful, but WITHOUT ANY
16*89a07cf8Schristos WARRANTY; without even the implied warranty of MERCHANTABILITY or
17*89a07cf8Schristos FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18*89a07cf8Schristos for more details.
19*89a07cf8Schristos
20*89a07cf8Schristos You should have received a copy of the GNU General Public License along
21*89a07cf8Schristos with groff; see the file COPYING. If not, write to the Free Software
22*89a07cf8Schristos Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
23*89a07cf8Schristos
24*89a07cf8Schristos #include "eqn.h"
25*89a07cf8Schristos #include "pbox.h"
26*89a07cf8Schristos
27*89a07cf8Schristos class script_box : public pointer_box {
28*89a07cf8Schristos private:
29*89a07cf8Schristos box *sub;
30*89a07cf8Schristos box *sup;
31*89a07cf8Schristos public:
32*89a07cf8Schristos script_box(box *, box *, box *);
33*89a07cf8Schristos ~script_box();
34*89a07cf8Schristos int compute_metrics(int);
35*89a07cf8Schristos void output();
36*89a07cf8Schristos void debug_print();
37*89a07cf8Schristos int left_is_italic();
38*89a07cf8Schristos void hint(unsigned);
39*89a07cf8Schristos void check_tabs(int);
40*89a07cf8Schristos };
41*89a07cf8Schristos
42*89a07cf8Schristos /* The idea is that the script should attach to the rightmost box
43*89a07cf8Schristos of a list. For example, given `2x sup 3', the superscript should
44*89a07cf8Schristos attach to `x' rather than `2x'. */
45*89a07cf8Schristos
make_script_box(box * nuc,box * sub,box * sup)46*89a07cf8Schristos box *make_script_box(box *nuc, box *sub, box *sup)
47*89a07cf8Schristos {
48*89a07cf8Schristos list_box *b = nuc->to_list_box();
49*89a07cf8Schristos if (b != 0) {
50*89a07cf8Schristos b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1],
51*89a07cf8Schristos sub,
52*89a07cf8Schristos sup);
53*89a07cf8Schristos return b;
54*89a07cf8Schristos }
55*89a07cf8Schristos else
56*89a07cf8Schristos return new script_box(nuc, sub, sup);
57*89a07cf8Schristos }
58*89a07cf8Schristos
script_box(box * pp,box * qq,box * rr)59*89a07cf8Schristos script_box::script_box(box *pp, box *qq, box *rr)
60*89a07cf8Schristos : pointer_box(pp), sub(qq), sup(rr)
61*89a07cf8Schristos {
62*89a07cf8Schristos }
63*89a07cf8Schristos
~script_box()64*89a07cf8Schristos script_box::~script_box()
65*89a07cf8Schristos {
66*89a07cf8Schristos delete sub;
67*89a07cf8Schristos delete sup;
68*89a07cf8Schristos }
69*89a07cf8Schristos
left_is_italic()70*89a07cf8Schristos int script_box::left_is_italic()
71*89a07cf8Schristos {
72*89a07cf8Schristos return p->left_is_italic();
73*89a07cf8Schristos }
74*89a07cf8Schristos
compute_metrics(int style)75*89a07cf8Schristos int script_box::compute_metrics(int style)
76*89a07cf8Schristos {
77*89a07cf8Schristos int res = p->compute_metrics(style);
78*89a07cf8Schristos p->compute_subscript_kern();
79*89a07cf8Schristos printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
80*89a07cf8Schristos if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
81*89a07cf8Schristos set_script_size();
82*89a07cf8Schristos printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
83*89a07cf8Schristos if (sub != 0)
84*89a07cf8Schristos sub->compute_metrics(cramped_style(script_style(style)));
85*89a07cf8Schristos if (sup != 0)
86*89a07cf8Schristos sup->compute_metrics(script_style(style));
87*89a07cf8Schristos // 18a
88*89a07cf8Schristos if (p->is_char()) {
89*89a07cf8Schristos printf(".nr " SUP_RAISE_FORMAT " 0\n", uid);
90*89a07cf8Schristos printf(".nr " SUB_LOWER_FORMAT " 0\n", uid);
91*89a07cf8Schristos }
92*89a07cf8Schristos else {
93*89a07cf8Schristos printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
94*89a07cf8Schristos uid, p->uid, sup_drop);
95*89a07cf8Schristos printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
96*89a07cf8Schristos uid, p->uid, sub_drop);
97*89a07cf8Schristos }
98*89a07cf8Schristos printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
99*89a07cf8Schristos if (sup == 0) {
100*89a07cf8Schristos assert(sub != 0);
101*89a07cf8Schristos // 18b
102*89a07cf8Schristos printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n["
103*89a07cf8Schristos HEIGHT_FORMAT "]-(%dM*4/5))\n",
104*89a07cf8Schristos uid, uid, sub1, sub->uid, x_height);
105*89a07cf8Schristos }
106*89a07cf8Schristos else {
107*89a07cf8Schristos // sup != 0
108*89a07cf8Schristos // 18c
109*89a07cf8Schristos int pos;
110*89a07cf8Schristos if (style == DISPLAY_STYLE)
111*89a07cf8Schristos pos = sup1;
112*89a07cf8Schristos else if (style & 1) // not cramped
113*89a07cf8Schristos pos = sup2;
114*89a07cf8Schristos else
115*89a07cf8Schristos pos = sup3;
116*89a07cf8Schristos printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT
117*89a07cf8Schristos "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n",
118*89a07cf8Schristos uid, uid, pos, sup->uid, x_height);
119*89a07cf8Schristos // 18d
120*89a07cf8Schristos if (sub != 0) {
121*89a07cf8Schristos printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n",
122*89a07cf8Schristos uid, uid, sub2);
123*89a07cf8Schristos // 18e
124*89a07cf8Schristos printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n["
125*89a07cf8Schristos SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n["
126*89a07cf8Schristos SUB_LOWER_FORMAT "]+(4*%dM)\n",
127*89a07cf8Schristos sup->uid, uid, sub->uid, uid, default_rule_thickness);
128*89a07cf8Schristos printf(".if \\n[" TEMP_REG "] \\{");
129*89a07cf8Schristos printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid);
130*89a07cf8Schristos printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT
131*89a07cf8Schristos "]+\\n[" DEPTH_FORMAT "]>?0\n",
132*89a07cf8Schristos x_height, uid, sup->uid);
133*89a07cf8Schristos printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid);
134*89a07cf8Schristos printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid);
135*89a07cf8Schristos printf(".\\}\n");
136*89a07cf8Schristos }
137*89a07cf8Schristos }
138*89a07cf8Schristos printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
139*89a07cf8Schristos if (sub != 0 && sup != 0)
140*89a07cf8Schristos printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n["
141*89a07cf8Schristos WIDTH_FORMAT "])+%dM)>?0\n",
142*89a07cf8Schristos sub->uid, p->uid, sup->uid, script_space);
143*89a07cf8Schristos else if (sub != 0)
144*89a07cf8Schristos printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n",
145*89a07cf8Schristos sub->uid, p->uid, script_space);
146*89a07cf8Schristos else if (sup != 0)
147*89a07cf8Schristos printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space);
148*89a07cf8Schristos else
149*89a07cf8Schristos printf("\n");
150*89a07cf8Schristos printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]",
151*89a07cf8Schristos uid, p->uid);
152*89a07cf8Schristos if (sup != 0)
153*89a07cf8Schristos printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
154*89a07cf8Schristos uid, sup->uid);
155*89a07cf8Schristos if (sub != 0)
156*89a07cf8Schristos printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])",
157*89a07cf8Schristos uid, sub->uid);
158*89a07cf8Schristos printf("\n");
159*89a07cf8Schristos printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]",
160*89a07cf8Schristos uid, p->uid);
161*89a07cf8Schristos if (sub != 0)
162*89a07cf8Schristos printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])",
163*89a07cf8Schristos uid, sub->uid);
164*89a07cf8Schristos if (sup != 0)
165*89a07cf8Schristos printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])",
166*89a07cf8Schristos uid, sup->uid);
167*89a07cf8Schristos printf("\n");
168*89a07cf8Schristos return res;
169*89a07cf8Schristos }
170*89a07cf8Schristos
output()171*89a07cf8Schristos void script_box::output()
172*89a07cf8Schristos {
173*89a07cf8Schristos p->output();
174*89a07cf8Schristos if (sup != 0) {
175*89a07cf8Schristos printf("\\Z" DELIMITER_CHAR);
176*89a07cf8Schristos printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
177*89a07cf8Schristos printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
178*89a07cf8Schristos sup->output();
179*89a07cf8Schristos printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
180*89a07cf8Schristos printf(DELIMITER_CHAR);
181*89a07cf8Schristos }
182*89a07cf8Schristos if (sub != 0) {
183*89a07cf8Schristos printf("\\Z" DELIMITER_CHAR);
184*89a07cf8Schristos printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
185*89a07cf8Schristos printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
186*89a07cf8Schristos printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid);
187*89a07cf8Schristos sub->output();
188*89a07cf8Schristos printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
189*89a07cf8Schristos printf(DELIMITER_CHAR);
190*89a07cf8Schristos }
191*89a07cf8Schristos printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
192*89a07cf8Schristos uid, p->uid);
193*89a07cf8Schristos }
194*89a07cf8Schristos
hint(unsigned flags)195*89a07cf8Schristos void script_box::hint(unsigned flags)
196*89a07cf8Schristos {
197*89a07cf8Schristos p->hint(flags & ~HINT_NEXT_IS_ITALIC);
198*89a07cf8Schristos }
199*89a07cf8Schristos
debug_print()200*89a07cf8Schristos void script_box::debug_print()
201*89a07cf8Schristos {
202*89a07cf8Schristos fprintf(stderr, "{ ");
203*89a07cf8Schristos p->debug_print();
204*89a07cf8Schristos fprintf(stderr, " }");
205*89a07cf8Schristos if (sub) {
206*89a07cf8Schristos fprintf(stderr, " sub { ");
207*89a07cf8Schristos sub->debug_print();
208*89a07cf8Schristos fprintf(stderr, " }");
209*89a07cf8Schristos }
210*89a07cf8Schristos if (sup) {
211*89a07cf8Schristos fprintf(stderr, " sup { ");
212*89a07cf8Schristos sup->debug_print();
213*89a07cf8Schristos fprintf(stderr, " }");
214*89a07cf8Schristos }
215*89a07cf8Schristos }
216*89a07cf8Schristos
check_tabs(int level)217*89a07cf8Schristos void script_box::check_tabs(int level)
218*89a07cf8Schristos {
219*89a07cf8Schristos if (sup)
220*89a07cf8Schristos sup->check_tabs(level + 1);
221*89a07cf8Schristos if (sub)
222*89a07cf8Schristos sub->check_tabs(level + 1);
223*89a07cf8Schristos p->check_tabs(level);
224*89a07cf8Schristos }
225