NetBSD/gnu/usr.bin/groff/eqn/sqrt.cc

180 lines
5.6 KiB
C++

// -*- C++ -*-
/* Copyright (C) 1989, 1990, 1991, 1992 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 2, 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 groff; see the file COPYING. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#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 "\\(sr"
#define RADICAL_EXTENSION_CHAR "\\(rn"
#define SQRT_CHAIN "\\[sr\\\\n[" INDEX_REG "]]"
#define BAR_CHAIN "\\[rn\\\\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[.s]\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[.s]\n");
printf(".ps \\n[" SIZE_FORMAT "]\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[rsb]-%dM<\\n[" TEMP_REG "]"
"&(\\\\n[.s]<\\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[.s]\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 "]\n", uid);
return r;
}
void sqrt_box::output()
{
printf("\\Z" DELIMITER_CHAR);
printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
printf("\\*[" SQRT_STRING_FORMAT "]", uid);
printf("\\s[\\n[" SIZE_FORMAT "]]", 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);
}
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);
}