xref: /netbsd-src/external/gpl2/groff/dist/src/preproc/eqn/script.cpp (revision 89a07cf815a29524268025a1139fac4c5190f765)
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