xref: /386bsd/usr/src/usr.bin/groff/eqn/sqrt.cc (revision a2142627)
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3      Written by James Clark (jjc@jclark.com)
4 
5 This file is part of groff.
6 
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11 
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING.  If not, write to the Free Software
19 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 
21 #include "eqn.h"
22 #include "pbox.h"
23 
24 
25 class sqrt_box : public pointer_box {
26 public:
27   sqrt_box(box *);
28   int compute_metrics(int style);
29   void output();
30   void debug_print();
31   void check_tabs(int);
32 };
33 
make_sqrt_box(box * pp)34 box *make_sqrt_box(box *pp)
35 {
36   return new sqrt_box(pp);
37 }
38 
sqrt_box(box * pp)39 sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
40 {
41 }
42 
43 #define SQRT_CHAR "\\(sr"
44 #define RADICAL_EXTENSION_CHAR "\\(rn"
45 
46 #define SQRT_CHAIN "\\[sr\\\\n[" INDEX_REG "]]"
47 #define BAR_CHAIN "\\[rn\\\\n[" INDEX_REG "]]"
48 
compute_metrics(int style)49 int sqrt_box::compute_metrics(int style)
50 {
51   // 11
52   int r = p->compute_metrics(cramped_style(style));
53   printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
54 	 "]+%dM+(%dM/4)\n",
55 	 p->uid, p->uid, default_rule_thickness,
56 	 (style > SCRIPT_STYLE ? x_height : default_rule_thickness));
57   printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
58   printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
59   printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
60   printf(".nr " SQRT_WIDTH_FORMAT
61 	 " 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
62 	 uid);
63   printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
64 	 default_rule_thickness);
65 
66   printf(".nr " INDEX_REG " 0\n"
67 	 ".de " TEMP_MACRO "\n"
68 	 ".ie c" SQRT_CHAIN " \\{"
69 	 ".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
70 	 ".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
71 	 ".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
72 	 ".nr " SQRT_WIDTH_FORMAT
73 	 " 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
74 	 ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
75 	 ".nr " INDEX_REG " +1\n"
76 	 "." TEMP_MACRO "\n"
77 	 ".\\}\\}\n"
78 	 ".el .nr " INDEX_REG " 0-1\n"
79 	 "..\n"
80 	 "." TEMP_MACRO "\n",
81 	 uid, uid, default_rule_thickness);
82 
83   printf(".if \\n[" INDEX_REG "]<0 \\{");
84 
85   // Determine the maximum point size
86   printf(".ps 1000\n");
87   printf(".nr " MAX_SIZE_REG " \\n[.s]\n");
88   printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
89   // We define a macro that will increase the current point size
90   // until we get a radical sign that's tall enough or we reach
91   // the maximum point size.
92   printf(".de " TEMP_MACRO "\n"
93 	 ".nr " SQRT_WIDTH_FORMAT
94 	 " 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
95 	 ".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "]"
96 	 "&(\\\\n[.s]<\\n[" MAX_SIZE_REG "]) \\{"
97 	 ".ps +1\n"
98 	 "." TEMP_MACRO "\n"
99 	 ".\\}\n"
100 	 "..\n"
101 	 "." TEMP_MACRO "\n",
102 	 uid, uid, default_rule_thickness);
103 
104   printf(".\\}\\}\n");
105 
106   printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
107   // set TEMP_REG to the amount by which the radical sign is too big
108   printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
109 	 default_rule_thickness);
110   // If TEMP_REG is negative, the bottom of the radical sign should
111   // be -TEMP_REG above the bottom of p. If it's positive, the bottom
112   // of the radical sign should be TEMP_REG/2 below the bottom of p.
113   // This calculates the amount by which the baseline of the radical
114   // should be raised.
115   printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
116 	 "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
117   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
118 	 ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
119 	 uid, p->uid, uid);
120   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
121 	 ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
122 	 uid, p->uid, uid);
123   // Do this last, so we don't lose height and depth information on
124   // the radical sign.
125   // Remember that the width of the bar might be greater than the width of p.
126 
127   printf(".nr " TEMP_REG " "
128 	 "\\n[" WIDTH_FORMAT "]"
129 	 ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
130 	 p->uid);
131   printf(".as " SQRT_STRING_FORMAT " "
132 	 "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
133 	 uid);
134   printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
135 	 "+\\n[" SQRT_WIDTH_FORMAT "]\n",
136 	 uid, uid);
137 
138   if (r)
139     printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
140   // the top of the bar might be higher than the top of the radical sign
141   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
142 	 ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
143 	 uid, p->uid, uid);
144   // put a bit of extra space above the bar
145   printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
146   printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
147   return r;
148 }
149 
output()150 void sqrt_box::output()
151 {
152   printf("\\Z" DELIMITER_CHAR);
153   printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
154   printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
155   printf("\\*[" SQRT_STRING_FORMAT "]", uid);
156   printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
157   printf(DELIMITER_CHAR);
158 
159   printf("\\Z" DELIMITER_CHAR);
160   printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
161 	 "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
162 	 uid, p->uid, uid);
163   p->output();
164   printf(DELIMITER_CHAR);
165 
166   printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
167 }
168 
debug_print()169 void sqrt_box::debug_print()
170 {
171   fprintf(stderr, "sqrt { ");
172   p->debug_print();
173   fprintf(stderr, " }");
174 }
175 
check_tabs(int level)176 void sqrt_box::check_tabs(int level)
177 {
178   p->check_tabs(level + 1);
179 }
180