1*89a07cf8Schristos /* $NetBSD: sqrt.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, 2003
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
28*89a07cf8Schristos class sqrt_box : public pointer_box {
29*89a07cf8Schristos public:
30*89a07cf8Schristos sqrt_box(box *);
31*89a07cf8Schristos int compute_metrics(int style);
32*89a07cf8Schristos void output();
33*89a07cf8Schristos void debug_print();
34*89a07cf8Schristos void check_tabs(int);
35*89a07cf8Schristos };
36*89a07cf8Schristos
make_sqrt_box(box * pp)37*89a07cf8Schristos box *make_sqrt_box(box *pp)
38*89a07cf8Schristos {
39*89a07cf8Schristos return new sqrt_box(pp);
40*89a07cf8Schristos }
41*89a07cf8Schristos
sqrt_box(box * pp)42*89a07cf8Schristos sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
43*89a07cf8Schristos {
44*89a07cf8Schristos }
45*89a07cf8Schristos
46*89a07cf8Schristos #define SQRT_CHAR "\\[sqrt]"
47*89a07cf8Schristos #define RADICAL_EXTENSION_CHAR "\\[sqrtex]"
48*89a07cf8Schristos
49*89a07cf8Schristos #define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]"
50*89a07cf8Schristos #define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]"
51*89a07cf8Schristos
compute_metrics(int style)52*89a07cf8Schristos int sqrt_box::compute_metrics(int style)
53*89a07cf8Schristos {
54*89a07cf8Schristos // 11
55*89a07cf8Schristos int r = p->compute_metrics(cramped_style(style));
56*89a07cf8Schristos printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
57*89a07cf8Schristos "]+%dM+(%dM/4)\n",
58*89a07cf8Schristos p->uid, p->uid, default_rule_thickness,
59*89a07cf8Schristos (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
60*89a07cf8Schristos printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
61*89a07cf8Schristos printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
62*89a07cf8Schristos printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
63*89a07cf8Schristos printf(".nr " SQRT_WIDTH_FORMAT
64*89a07cf8Schristos " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
65*89a07cf8Schristos uid);
66*89a07cf8Schristos printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
67*89a07cf8Schristos default_rule_thickness);
68*89a07cf8Schristos
69*89a07cf8Schristos printf(".nr " INDEX_REG " 0\n"
70*89a07cf8Schristos ".de " TEMP_MACRO "\n"
71*89a07cf8Schristos ".ie c" SQRT_CHAIN " \\{"
72*89a07cf8Schristos ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
73*89a07cf8Schristos ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
74*89a07cf8Schristos ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
75*89a07cf8Schristos ".nr " SQRT_WIDTH_FORMAT
76*89a07cf8Schristos " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
77*89a07cf8Schristos ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
78*89a07cf8Schristos ".nr " INDEX_REG " +1\n"
79*89a07cf8Schristos "." TEMP_MACRO "\n"
80*89a07cf8Schristos ".\\}\\}\n"
81*89a07cf8Schristos ".el .nr " INDEX_REG " 0-1\n"
82*89a07cf8Schristos "..\n"
83*89a07cf8Schristos "." TEMP_MACRO "\n",
84*89a07cf8Schristos uid, uid, default_rule_thickness);
85*89a07cf8Schristos
86*89a07cf8Schristos printf(".if \\n[" INDEX_REG "]<0 \\{");
87*89a07cf8Schristos
88*89a07cf8Schristos // Determine the maximum point size
89*89a07cf8Schristos printf(".ps 1000\n");
90*89a07cf8Schristos printf(".nr " MAX_SIZE_REG " \\n[.ps]\n");
91*89a07cf8Schristos printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
92*89a07cf8Schristos // We define a macro that will increase the current point size
93*89a07cf8Schristos // until we get a radical sign that's tall enough or we reach
94*89a07cf8Schristos // the maximum point size.
95*89a07cf8Schristos printf(".de " TEMP_MACRO "\n"
96*89a07cf8Schristos ".nr " SQRT_WIDTH_FORMAT
97*89a07cf8Schristos " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
98*89a07cf8Schristos ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]"
99*89a07cf8Schristos "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{"
100*89a07cf8Schristos ".ps +1\n"
101*89a07cf8Schristos "." TEMP_MACRO "\n"
102*89a07cf8Schristos ".\\}\n"
103*89a07cf8Schristos "..\n"
104*89a07cf8Schristos "." TEMP_MACRO "\n",
105*89a07cf8Schristos uid, uid, default_rule_thickness);
106*89a07cf8Schristos
107*89a07cf8Schristos printf(".\\}\\}\n");
108*89a07cf8Schristos
109*89a07cf8Schristos printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
110*89a07cf8Schristos // set TEMP_REG to the amount by which the radical sign is too big
111*89a07cf8Schristos printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
112*89a07cf8Schristos default_rule_thickness);
113*89a07cf8Schristos // If TEMP_REG is negative, the bottom of the radical sign should
114*89a07cf8Schristos // be -TEMP_REG above the bottom of p. If it's positive, the bottom
115*89a07cf8Schristos // of the radical sign should be TEMP_REG/2 below the bottom of p.
116*89a07cf8Schristos // This calculates the amount by which the baseline of the radical
117*89a07cf8Schristos // should be raised.
118*89a07cf8Schristos printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
119*89a07cf8Schristos "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
120*89a07cf8Schristos printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
121*89a07cf8Schristos ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
122*89a07cf8Schristos uid, p->uid, uid);
123*89a07cf8Schristos printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
124*89a07cf8Schristos ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
125*89a07cf8Schristos uid, p->uid, uid);
126*89a07cf8Schristos // Do this last, so we don't lose height and depth information on
127*89a07cf8Schristos // the radical sign.
128*89a07cf8Schristos // Remember that the width of the bar might be greater than the width of p.
129*89a07cf8Schristos
130*89a07cf8Schristos printf(".nr " TEMP_REG " "
131*89a07cf8Schristos "\\n[" WIDTH_FORMAT "]"
132*89a07cf8Schristos ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
133*89a07cf8Schristos p->uid);
134*89a07cf8Schristos printf(".as " SQRT_STRING_FORMAT " "
135*89a07cf8Schristos "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
136*89a07cf8Schristos uid);
137*89a07cf8Schristos printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
138*89a07cf8Schristos "+\\n[" SQRT_WIDTH_FORMAT "]\n",
139*89a07cf8Schristos uid, uid);
140*89a07cf8Schristos
141*89a07cf8Schristos if (r)
142*89a07cf8Schristos printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
143*89a07cf8Schristos // the top of the bar might be higher than the top of the radical sign
144*89a07cf8Schristos printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
145*89a07cf8Schristos ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
146*89a07cf8Schristos uid, p->uid, uid);
147*89a07cf8Schristos // put a bit of extra space above the bar
148*89a07cf8Schristos printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
149*89a07cf8Schristos printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
150*89a07cf8Schristos return r;
151*89a07cf8Schristos }
152*89a07cf8Schristos
output()153*89a07cf8Schristos void sqrt_box::output()
154*89a07cf8Schristos {
155*89a07cf8Schristos printf("\\Z" DELIMITER_CHAR);
156*89a07cf8Schristos printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
157*89a07cf8Schristos printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
158*89a07cf8Schristos printf("\\*[" SQRT_STRING_FORMAT "]", uid);
159*89a07cf8Schristos printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
160*89a07cf8Schristos printf(DELIMITER_CHAR);
161*89a07cf8Schristos
162*89a07cf8Schristos printf("\\Z" DELIMITER_CHAR);
163*89a07cf8Schristos printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
164*89a07cf8Schristos "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
165*89a07cf8Schristos uid, p->uid, uid);
166*89a07cf8Schristos p->output();
167*89a07cf8Schristos printf(DELIMITER_CHAR);
168*89a07cf8Schristos
169*89a07cf8Schristos printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
170*89a07cf8Schristos }
171*89a07cf8Schristos
debug_print()172*89a07cf8Schristos void sqrt_box::debug_print()
173*89a07cf8Schristos {
174*89a07cf8Schristos fprintf(stderr, "sqrt { ");
175*89a07cf8Schristos p->debug_print();
176*89a07cf8Schristos fprintf(stderr, " }");
177*89a07cf8Schristos }
178*89a07cf8Schristos
check_tabs(int level)179*89a07cf8Schristos void sqrt_box::check_tabs(int level)
180*89a07cf8Schristos {
181*89a07cf8Schristos p->check_tabs(level + 1);
182*89a07cf8Schristos }
183