294 lines
7.6 KiB
C++
294 lines
7.6 KiB
C++
|
// -*- C++ -*-
|
||
|
/* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
|
||
|
Written by James Clark (jjc@jclark.uucp)
|
||
|
|
||
|
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 1, 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 LICENSE. If not, write to the Free Software
|
||
|
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||
|
// piles and matrices
|
||
|
|
||
|
#include "eqn.h"
|
||
|
#include "pbox.h"
|
||
|
|
||
|
// SUP_RAISE_FORMAT gives the first baseline
|
||
|
// BASELINE_SEP_FORMAT gives the separation between baselines
|
||
|
|
||
|
int pile_box::compute_metrics(int style)
|
||
|
{
|
||
|
int i;
|
||
|
for (i = 0; i < col.len; i++)
|
||
|
col.p[i]->compute_metrics(style);
|
||
|
printf(".nr " WIDTH_FORMAT " 0", uid);
|
||
|
for (i = 0; i < col.len; i++)
|
||
|
printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid);
|
||
|
printf("\n");
|
||
|
printf(".nr " BASELINE_SEP_FORMAT " %dM",
|
||
|
uid, baseline_sep+col.space);
|
||
|
for (i = 1; i < col.len; i++)
|
||
|
printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
|
||
|
col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5);
|
||
|
// round it so that it's a multiple of the vertical resolution
|
||
|
printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
|
||
|
|
||
|
printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
|
||
|
"+%dM\n",
|
||
|
uid, uid, col.len-1, axis_height - shift_down);
|
||
|
printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n["
|
||
|
HEIGHT_FORMAT "]\n",
|
||
|
uid, uid, col.p[0]->uid);
|
||
|
printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n["
|
||
|
DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n",
|
||
|
uid, uid, col.len-1, col.p[col.len-1]->uid, uid);
|
||
|
return FOUND_NOTHING;
|
||
|
}
|
||
|
|
||
|
void pile_box::output()
|
||
|
{
|
||
|
int i;
|
||
|
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
|
||
|
for (i = 0; i < col.len; i++) {
|
||
|
switch (col.align) {
|
||
|
case LEFT_ALIGN:
|
||
|
break;
|
||
|
case CENTER_ALIGN:
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
|
||
|
uid, col.p[i]->uid);
|
||
|
break;
|
||
|
case RIGHT_ALIGN:
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
|
||
|
uid, col.p[i]->uid);
|
||
|
break;
|
||
|
default:
|
||
|
assert(0);
|
||
|
}
|
||
|
col.p[i]->output();
|
||
|
printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid);
|
||
|
switch (col.align) {
|
||
|
case LEFT_ALIGN:
|
||
|
break;
|
||
|
case CENTER_ALIGN:
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
|
||
|
col.p[i]->uid, uid);
|
||
|
break;
|
||
|
case RIGHT_ALIGN:
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
|
||
|
col.p[i]->uid, uid);
|
||
|
break;
|
||
|
default:
|
||
|
assert(0);
|
||
|
}
|
||
|
if (i != col.len - 1)
|
||
|
printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
|
||
|
}
|
||
|
printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
|
||
|
printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid);
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
|
||
|
}
|
||
|
|
||
|
pile_box::pile_box(box *pp) : col(pp)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void pile_box::check_tabs(int level)
|
||
|
{
|
||
|
col.list_check_tabs(level);
|
||
|
}
|
||
|
|
||
|
void pile_box::debug_print()
|
||
|
{
|
||
|
col.debug_print("pile");
|
||
|
}
|
||
|
|
||
|
int matrix_box::compute_metrics(int style)
|
||
|
{
|
||
|
int i, j;
|
||
|
int maxlen = 0;
|
||
|
int space = 0;
|
||
|
for (i = 0; i < len; i++) {
|
||
|
for (j = 0; j < p[i]->len; j++)
|
||
|
p[i]->p[j]->compute_metrics(style);
|
||
|
if (p[i]->len > maxlen)
|
||
|
maxlen = p[i]->len;
|
||
|
if (p[i]->space > space)
|
||
|
space = p[i]->space;
|
||
|
}
|
||
|
for (i = 0; i < len; i++) {
|
||
|
printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i);
|
||
|
for (j = 0; j < p[i]->len; j++)
|
||
|
printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid);
|
||
|
printf("\n");
|
||
|
}
|
||
|
printf(".nr " WIDTH_FORMAT " %dM",
|
||
|
uid, column_sep*(len-1)+2*matrix_side_sep);
|
||
|
for (i = 0; i < len; i++)
|
||
|
printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i);
|
||
|
printf("\n");
|
||
|
printf(".nr " BASELINE_SEP_FORMAT " %dM",
|
||
|
uid, baseline_sep+space);
|
||
|
for (i = 0; i < len; i++)
|
||
|
for (j = 1; j < p[i]->len; j++)
|
||
|
printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)",
|
||
|
p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5);
|
||
|
// round it so that it's a multiple of the vertical resolution
|
||
|
printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n");
|
||
|
printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2"
|
||
|
"+%dM\n",
|
||
|
uid, uid, maxlen-1, axis_height - shift_down);
|
||
|
printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+(0",
|
||
|
uid, uid);
|
||
|
for (i = 0; i < len; i++)
|
||
|
printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid);
|
||
|
printf(")\n");
|
||
|
printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n["
|
||
|
SUP_RAISE_FORMAT "]+(0",
|
||
|
uid, uid, maxlen-1, uid);
|
||
|
for (i = 0; i < len; i++)
|
||
|
if (p[i]->len == maxlen)
|
||
|
printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[maxlen-1]->uid);
|
||
|
printf(")\n");
|
||
|
return FOUND_NOTHING;
|
||
|
}
|
||
|
|
||
|
void matrix_box::output()
|
||
|
{
|
||
|
printf("\\h'%dM'", matrix_side_sep);
|
||
|
for (int i = 0; i < len; i++) {
|
||
|
int j;
|
||
|
printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
|
||
|
for (j = 0; j < p[i]->len; j++) {
|
||
|
switch (p[i]->align) {
|
||
|
case LEFT_ALIGN:
|
||
|
break;
|
||
|
case CENTER_ALIGN:
|
||
|
printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'",
|
||
|
uid, i, p[i]->p[j]->uid);
|
||
|
break;
|
||
|
case RIGHT_ALIGN:
|
||
|
printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'",
|
||
|
uid, i, p[i]->p[j]->uid);
|
||
|
break;
|
||
|
default:
|
||
|
assert(0);
|
||
|
}
|
||
|
p[i]->p[j]->output();
|
||
|
printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid);
|
||
|
switch (p[i]->align) {
|
||
|
case LEFT_ALIGN:
|
||
|
break;
|
||
|
case CENTER_ALIGN:
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'",
|
||
|
p[i]->p[j]->uid, uid, i);
|
||
|
break;
|
||
|
case RIGHT_ALIGN:
|
||
|
printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'",
|
||
|
p[i]->p[j]->uid, uid, i);
|
||
|
break;
|
||
|
default:
|
||
|
assert(0);
|
||
|
}
|
||
|
if (j != p[i]->len - 1)
|
||
|
printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid);
|
||
|
}
|
||
|
printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
|
||
|
printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid);
|
||
|
printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i);
|
||
|
if (i != len - 1)
|
||
|
printf("\\h'%dM'", column_sep);
|
||
|
}
|
||
|
printf("\\h'%dM'", matrix_side_sep);
|
||
|
}
|
||
|
|
||
|
matrix_box::matrix_box(column *pp)
|
||
|
{
|
||
|
p = new column*[10];
|
||
|
for (int i = 0; i < 10; i++)
|
||
|
p[i] = 0;
|
||
|
maxlen = 10;
|
||
|
len = 1;
|
||
|
p[0] = pp;
|
||
|
}
|
||
|
|
||
|
matrix_box::~matrix_box()
|
||
|
{
|
||
|
for (int i = 0; i < len; i++)
|
||
|
delete p[i];
|
||
|
delete p;
|
||
|
}
|
||
|
|
||
|
void matrix_box::append(column *pp)
|
||
|
{
|
||
|
if (len + 1 > maxlen) {
|
||
|
column **oldp = p;
|
||
|
maxlen *= 2;
|
||
|
p = new column*[maxlen];
|
||
|
memcpy(p, oldp, sizeof(column*)*len);
|
||
|
delete oldp;
|
||
|
}
|
||
|
p[len++] = pp;
|
||
|
}
|
||
|
|
||
|
void matrix_box::check_tabs(int level)
|
||
|
{
|
||
|
for (int i = 0; i < len; i++)
|
||
|
p[i]->list_check_tabs(level);
|
||
|
}
|
||
|
|
||
|
void matrix_box::debug_print()
|
||
|
{
|
||
|
fprintf(stderr, "matrix { ");
|
||
|
p[0]->debug_print("col");
|
||
|
for (int i = 1; i < len; i++) {
|
||
|
fprintf(stderr, " ");
|
||
|
p[i]->debug_print("col");
|
||
|
}
|
||
|
fprintf(stderr, " }");
|
||
|
}
|
||
|
|
||
|
column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void column::set_alignment(alignment a)
|
||
|
{
|
||
|
align = a;
|
||
|
}
|
||
|
|
||
|
void column::set_space(int n)
|
||
|
{
|
||
|
space = n;
|
||
|
}
|
||
|
|
||
|
void column::debug_print(const char *s)
|
||
|
{
|
||
|
char c = '\0'; // shut up -Wall
|
||
|
switch (align) {
|
||
|
case LEFT_ALIGN:
|
||
|
c = 'l';
|
||
|
break;
|
||
|
case RIGHT_ALIGN:
|
||
|
c = 'r';
|
||
|
break;
|
||
|
case CENTER_ALIGN:
|
||
|
c = 'c';
|
||
|
break;
|
||
|
default:
|
||
|
assert(0);
|
||
|
}
|
||
|
fprintf(stderr, "%c%s %d { ", c, s, space);
|
||
|
list_debug_print(" above ");
|
||
|
fprintf(stderr, " }");
|
||
|
}
|
||
|
|