Merge branch 'vendor/OPENSSL'
[dragonfly.git] / contrib / groff / src / preproc / eqn / sqrt.cpp
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2003, 2007, 2008, 2009
3    Free Software Foundation, Inc.
4      Written by James Clark (jjc@jclark.com)
5
6 This file is part of groff.
7
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 3 of the License, or
11 (at your option) any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
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
34 box *make_sqrt_box(box *pp)
35 {
36   return new sqrt_box(pp);
37 }
38
39 sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
40 {
41 }
42
43 #define SQRT_CHAR "\\[sqrt]"
44 #define RADICAL_EXTENSION_CHAR "\\[sqrtex]"
45
46 #define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]"
47 #define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]"
48
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[.ps]\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[.ps]\n");
88   printf(".ps \\n[" SIZE_FORMAT "]u\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]"
96          "&(\\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "])"
97          "&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{"
98          ".ps +1\n"
99          "." TEMP_MACRO "\n"
100          ".\\}\n"
101          "..\n"
102          "." TEMP_MACRO "\n",
103          uid, uid, default_rule_thickness);
104   
105   printf(".\\}\\}\n");
106
107   printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
108   // set TEMP_REG to the amount by which the radical sign is too big
109   printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
110          default_rule_thickness);
111   // If TEMP_REG is negative, the bottom of the radical sign should
112   // be -TEMP_REG above the bottom of p. If it's positive, the bottom
113   // of the radical sign should be TEMP_REG/2 below the bottom of p.
114   // This calculates the amount by which the baseline of the radical
115   // should be raised.
116   printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
117          "-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
118   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
119          ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
120          uid, p->uid, uid);
121   printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
122          ">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
123          uid, p->uid, uid);
124   // Do this last, so we don't lose height and depth information on
125   // the radical sign.
126   // Remember that the width of the bar might be greater than the width of p.
127
128   printf(".nr " TEMP_REG " "
129          "\\n[" WIDTH_FORMAT "]"
130          ">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
131          p->uid);
132   printf(".as " SQRT_STRING_FORMAT " "
133          "\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
134          uid);
135   printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
136          "+\\n[" SQRT_WIDTH_FORMAT "]\n",
137          uid, uid);
138
139   if (r)
140     printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
141   // the top of the bar might be higher than the top of the radical sign
142   printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
143          ">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
144          uid, p->uid, uid);
145   // put a bit of extra space above the bar
146   printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
147   printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
148   return r;
149 }
150
151 void sqrt_box::output()
152 {
153   if (output_format == troff) {
154     printf("\\Z" DELIMITER_CHAR);
155     printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
156     printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
157     printf("\\*[" SQRT_STRING_FORMAT "]", uid);
158     printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
159     printf(DELIMITER_CHAR);
160
161     printf("\\Z" DELIMITER_CHAR);
162     printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
163            "+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
164            uid, p->uid, uid);
165     p->output();
166     printf(DELIMITER_CHAR);
167
168     printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
169   }
170   else if (output_format == mathml) {
171     printf("<msqrt>");
172     p->output();
173     printf("</msqrt>");
174   }
175 }
176
177 void sqrt_box::debug_print()
178 {
179   fprintf(stderr, "sqrt { ");
180   p->debug_print();
181   fprintf(stderr, " }");
182 }
183
184 void sqrt_box::check_tabs(int level)
185 {
186   p->check_tabs(level + 1);
187 }