// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2003, 2007, 2008, 2009
Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.com)
This file is part of groff.
groff is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or
(at your option) any later version.
groff is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include "eqn.h"
#include "pbox.h"
class sqrt_box : public pointer_box {
public:
sqrt_box(box *);
int compute_metrics(int style);
void output();
void debug_print();
void check_tabs(int);
};
box *make_sqrt_box(box *pp)
{
return new sqrt_box(pp);
}
sqrt_box::sqrt_box(box *pp) : pointer_box(pp)
{
}
#define SQRT_CHAR "\\[sqrt]"
#define RADICAL_EXTENSION_CHAR "\\[sqrtex]"
#define SQRT_CHAIN "\\[sqrt\\\\n[" INDEX_REG "]]"
#define BAR_CHAIN "\\[sqrtex\\\\n[" INDEX_REG "]]"
int sqrt_box::compute_metrics(int style)
{
// 11
int r = p->compute_metrics(cramped_style(style));
printf(".nr " TEMP_REG " \\n[" HEIGHT_FORMAT "]+\\n[" DEPTH_FORMAT
"]+%dM+(%dM/4)\n",
p->uid, p->uid, default_rule_thickness,
(style > SCRIPT_STYLE ? x_height : default_rule_thickness));
printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
printf(".ds " SQRT_STRING_FORMAT " " SQRT_CHAR "\n", uid);
printf(".ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n");
printf(".nr " SQRT_WIDTH_FORMAT
" 0\\w" DELIMITER_CHAR SQRT_CHAR DELIMITER_CHAR "\n",
uid);
printf(".if \\n[rst]-\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{",
default_rule_thickness);
printf(".nr " INDEX_REG " 0\n"
".de " TEMP_MACRO "\n"
".ie c" SQRT_CHAIN " \\{"
".ds " SQRT_STRING_FORMAT " " SQRT_CHAIN "\n"
".ie c" BAR_CHAIN " .ds " BAR_STRING " " BAR_CHAIN "\n"
".el .ds " BAR_STRING " " RADICAL_EXTENSION_CHAR "\n"
".nr " SQRT_WIDTH_FORMAT
" 0\\w" DELIMITER_CHAR SQRT_CHAIN DELIMITER_CHAR "\n"
".if \\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "] \\{"
".nr " INDEX_REG " +1\n"
"." TEMP_MACRO "\n"
".\\}\\}\n"
".el .nr " INDEX_REG " 0-1\n"
"..\n"
"." TEMP_MACRO "\n",
uid, uid, default_rule_thickness);
printf(".if \\n[" INDEX_REG "]<0 \\{");
// Determine the maximum point size
printf(".ps 1000\n");
printf(".nr " MAX_SIZE_REG " \\n[.ps]\n");
printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
// We define a macro that will increase the current point size
// until we get a radical sign that's tall enough or we reach
// the maximum point size.
printf(".de " TEMP_MACRO "\n"
".nr " SQRT_WIDTH_FORMAT
" 0\\w" DELIMITER_CHAR "\\*[" SQRT_STRING_FORMAT "]" DELIMITER_CHAR "\n"
".if \\\\n[rst]"
"&(\\\\n[rst]-\\\\n[rsb]-%dM<\\n[" TEMP_REG "])"
"&(\\\\n[.ps]<\\n[" MAX_SIZE_REG "]) \\{"
".ps +1\n"
"." TEMP_MACRO "\n"
".\\}\n"
"..\n"
"." TEMP_MACRO "\n",
uid, uid, default_rule_thickness);
printf(".\\}\\}\n");
printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
// set TEMP_REG to the amount by which the radical sign is too big
printf(".nr " TEMP_REG " \\n[rst]-\\n[rsb]-%dM-\\n[" TEMP_REG "]\n",
default_rule_thickness);
// If TEMP_REG is negative, the bottom of the radical sign should
// be -TEMP_REG above the bottom of p. If it's positive, the bottom
// of the radical sign should be TEMP_REG/2 below the bottom of p.
// This calculates the amount by which the baseline of the radical
// should be raised.
printf(".nr " SUP_RAISE_FORMAT " (-\\n[" TEMP_REG "]>?(-\\n[" TEMP_REG "]/2))"
"-\\n[rsb]-\\n[" DEPTH_FORMAT "]\n", uid, p->uid);
printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
uid, p->uid, uid);
printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
">?(-\\n[" SUP_RAISE_FORMAT "]-\\n[rsb])\n",
uid, p->uid, uid);
// Do this last, so we don't lose height and depth information on
// the radical sign.
// Remember that the width of the bar might be greater than the width of p.
printf(".nr " TEMP_REG " "
"\\n[" WIDTH_FORMAT "]"
">?\\w" DELIMITER_CHAR "\\*[" BAR_STRING "]" DELIMITER_CHAR "\n",
p->uid);
printf(".as " SQRT_STRING_FORMAT " "
"\\l'\\n[" TEMP_REG "]u\\&\\*[" BAR_STRING "]'\n",
uid);
printf(".nr " WIDTH_FORMAT " \\n[" TEMP_REG "]"
"+\\n[" SQRT_WIDTH_FORMAT "]\n",
uid, uid);
if (r)
printf(".nr " MARK_REG " +\\n[" SQRT_WIDTH_FORMAT "]\n", uid);
// the top of the bar might be higher than the top of the radical sign
printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]"
">?(\\n[" SUP_RAISE_FORMAT "]+\\n[rst])\n",
uid, p->uid, uid);
// put a bit of extra space above the bar
printf(".nr " HEIGHT_FORMAT " +%dM\n", uid, default_rule_thickness);
printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
return r;
}
void sqrt_box::output()
{
if (output_format == troff) {
printf("\\Z" DELIMITER_CHAR);
printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
printf("\\*[" SQRT_STRING_FORMAT "]", uid);
printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
printf(DELIMITER_CHAR);
printf("\\Z" DELIMITER_CHAR);
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u"
"+\\n[" SQRT_WIDTH_FORMAT "]u/2u'",
uid, p->uid, uid);
p->output();
printf(DELIMITER_CHAR);
printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
}
else if (output_format == mathml) {
printf("");
p->output();
printf("");
}
}
void sqrt_box::debug_print()
{
fprintf(stderr, "sqrt { ");
p->debug_print();
fprintf(stderr, " }");
}
void sqrt_box::check_tabs(int level)
{
p->check_tabs(level + 1);
}