196 lines
5.2 KiB
C++
196 lines
5.2 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||
|
|
||
|
#include "eqn.h"
|
||
|
#include "pbox.h"
|
||
|
|
||
|
class limit_box : public box {
|
||
|
private:
|
||
|
box *p;
|
||
|
box *from;
|
||
|
box *to;
|
||
|
public:
|
||
|
limit_box(box *, box *, box *);
|
||
|
~limit_box();
|
||
|
int compute_metrics(int);
|
||
|
void output();
|
||
|
void debug_print();
|
||
|
void check_tabs(int);
|
||
|
};
|
||
|
|
||
|
box *make_limit_box(box *pp, box *qq, box *rr)
|
||
|
{
|
||
|
return new limit_box(pp, qq, rr);
|
||
|
}
|
||
|
|
||
|
limit_box::limit_box(box *pp, box *qq, box *rr)
|
||
|
: p(pp), from(qq), to(rr)
|
||
|
{
|
||
|
spacing_type = p->spacing_type;
|
||
|
}
|
||
|
|
||
|
limit_box::~limit_box()
|
||
|
{
|
||
|
delete p;
|
||
|
delete from;
|
||
|
delete to;
|
||
|
}
|
||
|
|
||
|
int limit_box::compute_metrics(int style)
|
||
|
{
|
||
|
printf(".nr " SIZE_FORMAT " \\n[.s]\n", uid);
|
||
|
if (!(style <= SCRIPT_STYLE && one_size_reduction_flag))
|
||
|
set_script_size();
|
||
|
printf(".nr " SMALL_SIZE_FORMAT " \\n[.s]\n", uid);
|
||
|
int res = 0;
|
||
|
int mark_uid = -1;
|
||
|
if (from != 0) {
|
||
|
res = from->compute_metrics(cramped_style(script_style(style)));
|
||
|
if (res)
|
||
|
mark_uid = from->uid;
|
||
|
}
|
||
|
if (to != 0) {
|
||
|
int r = to->compute_metrics(script_style(style));
|
||
|
if (res && r)
|
||
|
error("multiple marks and lineups");
|
||
|
else {
|
||
|
mark_uid = to->uid;
|
||
|
res = r;
|
||
|
}
|
||
|
}
|
||
|
printf(".ps \\n[" SIZE_FORMAT "]\n", uid);
|
||
|
int r = p->compute_metrics(style);
|
||
|
p->compute_subscript_kern();
|
||
|
if (res && r)
|
||
|
error("multiple marks and lineups");
|
||
|
else {
|
||
|
mark_uid = p->uid;
|
||
|
res = r;
|
||
|
}
|
||
|
printf(".nr " LEFT_WIDTH_FORMAT " "
|
||
|
"0\\n[" WIDTH_FORMAT "]",
|
||
|
uid, p->uid);
|
||
|
if (from != 0)
|
||
|
printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
|
||
|
p->uid, from->uid);
|
||
|
if (to != 0)
|
||
|
printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
|
||
|
p->uid, to->uid);
|
||
|
printf("/2\n");
|
||
|
printf(".nr " WIDTH_FORMAT " "
|
||
|
"0\\n[" WIDTH_FORMAT "]",
|
||
|
uid, p->uid);
|
||
|
if (from != 0)
|
||
|
printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
|
||
|
p->uid, from->uid);
|
||
|
if (to != 0)
|
||
|
printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])",
|
||
|
p->uid, to->uid);
|
||
|
printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid);
|
||
|
printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid);
|
||
|
if (to != 0)
|
||
|
printf(">?\\n[" WIDTH_FORMAT "]", to->uid);
|
||
|
if (from != 0)
|
||
|
printf(">?\\n[" WIDTH_FORMAT "]", from->uid);
|
||
|
printf("\n");
|
||
|
if (res)
|
||
|
printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]"
|
||
|
"-(\\n[" WIDTH_FORMAT "]/2))\n",
|
||
|
uid, mark_uid);
|
||
|
if (to != 0) {
|
||
|
printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT
|
||
|
"]>?%dM+\\n[" HEIGHT_FORMAT "]\n",
|
||
|
uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid);
|
||
|
printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
|
||
|
HEIGHT_FORMAT "]+%dM\n",
|
||
|
uid, uid, to->uid, big_op_spacing5);
|
||
|
}
|
||
|
else
|
||
|
printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
|
||
|
if (from != 0) {
|
||
|
printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT
|
||
|
"]>?%dM+\\n[" DEPTH_FORMAT "]\n",
|
||
|
uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid);
|
||
|
printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n["
|
||
|
DEPTH_FORMAT "]+%dM\n",
|
||
|
uid, uid, from->uid, big_op_spacing5);
|
||
|
}
|
||
|
else
|
||
|
printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
void limit_box::output()
|
||
|
{
|
||
|
printf("\\s[\\n[" SMALL_SIZE_FORMAT "]]", uid);
|
||
|
if (to != 0) {
|
||
|
printf("\\Z" DELIMITER_CHAR);
|
||
|
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
|
||
|
printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
|
||
|
"+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'",
|
||
|
uid, to->uid, p->uid);
|
||
|
to->output();
|
||
|
printf(DELIMITER_CHAR);
|
||
|
}
|
||
|
if (from != 0) {
|
||
|
printf("\\Z" DELIMITER_CHAR);
|
||
|
printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid);
|
||
|
printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
|
||
|
"+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'",
|
||
|
uid, p->uid, from->uid);
|
||
|
from->output();
|
||
|
printf(DELIMITER_CHAR);
|
||
|
}
|
||
|
printf("\\s[\\n[" SIZE_FORMAT "]]", uid);
|
||
|
printf("\\Z" DELIMITER_CHAR);
|
||
|
printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u"
|
||
|
"-(\\n[" WIDTH_FORMAT "]u/2u)'",
|
||
|
uid, p->uid);
|
||
|
p->output();
|
||
|
printf(DELIMITER_CHAR);
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
|
||
|
}
|
||
|
|
||
|
void limit_box::debug_print()
|
||
|
{
|
||
|
fprintf(stderr, "{ ");
|
||
|
p->debug_print();
|
||
|
fprintf(stderr, " }");
|
||
|
if (from) {
|
||
|
fprintf(stderr, " from { ");
|
||
|
from->debug_print();
|
||
|
fprintf(stderr, " }");
|
||
|
}
|
||
|
if (to) {
|
||
|
fprintf(stderr, " to { ");
|
||
|
to->debug_print();
|
||
|
fprintf(stderr, " }");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void limit_box::check_tabs(int level)
|
||
|
{
|
||
|
if (to)
|
||
|
to->check_tabs(level + 1);
|
||
|
if (from)
|
||
|
from->check_tabs(level + 1);
|
||
|
p->check_tabs(level + 1);
|
||
|
}
|