1114402Sru// -*- C++ -*- 2151497Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc. 3114402Sru Written by James Clark (jjc@jclark.com) 4114402Sru 5114402SruThis file is part of groff. 6114402Sru 7114402Srugroff is free software; you can redistribute it and/or modify it under 8114402Sruthe terms of the GNU General Public License as published by the Free 9114402SruSoftware Foundation; either version 2, or (at your option) any later 10114402Sruversion. 11114402Sru 12114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 13114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 14114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15114402Srufor more details. 16114402Sru 17114402SruYou should have received a copy of the GNU General Public License along 18114402Sruwith groff; see the file COPYING. If not, write to the Free Software 19151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 20114402Sru// piles and matrices 21114402Sru 22114402Sru#include "eqn.h" 23114402Sru#include "pbox.h" 24114402Sru 25114402Sru// SUP_RAISE_FORMAT gives the first baseline 26114402Sru// BASELINE_SEP_FORMAT gives the separation between baselines 27114402Sru 28114402Sruint pile_box::compute_metrics(int style) 29114402Sru{ 30114402Sru int i; 31114402Sru for (i = 0; i < col.len; i++) 32114402Sru col.p[i]->compute_metrics(style); 33114402Sru printf(".nr " WIDTH_FORMAT " 0", uid); 34114402Sru for (i = 0; i < col.len; i++) 35114402Sru printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid); 36114402Sru printf("\n"); 37114402Sru printf(".nr " BASELINE_SEP_FORMAT " %dM", 38114402Sru uid, baseline_sep+col.space); 39114402Sru for (i = 1; i < col.len; i++) 40114402Sru printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", 41114402Sru col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5); 42114402Sru // round it so that it's a multiple of the vertical resolution 43114402Sru printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); 44114402Sru 45114402Sru printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" 46114402Sru "+%dM\n", 47114402Sru uid, uid, col.len-1, axis_height - shift_down); 48114402Sru printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" 49114402Sru HEIGHT_FORMAT "]\n", 50114402Sru uid, uid, col.p[0]->uid); 51114402Sru printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n[" 52114402Sru DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n", 53114402Sru uid, uid, col.len-1, col.p[col.len-1]->uid, uid); 54114402Sru return FOUND_NOTHING; 55114402Sru} 56114402Sru 57114402Sruvoid pile_box::output() 58114402Sru{ 59114402Sru int i; 60114402Sru printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 61114402Sru for (i = 0; i < col.len; i++) { 62114402Sru switch (col.align) { 63114402Sru case LEFT_ALIGN: 64114402Sru break; 65114402Sru case CENTER_ALIGN: 66114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 67114402Sru uid, col.p[i]->uid); 68114402Sru break; 69114402Sru case RIGHT_ALIGN: 70114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 71114402Sru uid, col.p[i]->uid); 72114402Sru break; 73114402Sru default: 74114402Sru assert(0); 75114402Sru } 76114402Sru col.p[i]->output(); 77114402Sru printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid); 78114402Sru switch (col.align) { 79114402Sru case LEFT_ALIGN: 80114402Sru break; 81114402Sru case CENTER_ALIGN: 82114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 83114402Sru col.p[i]->uid, uid); 84114402Sru break; 85114402Sru case RIGHT_ALIGN: 86114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 87114402Sru col.p[i]->uid, uid); 88114402Sru break; 89114402Sru default: 90114402Sru assert(0); 91114402Sru } 92114402Sru if (i != col.len - 1) 93114402Sru printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); 94114402Sru } 95114402Sru printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 96114402Sru printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid); 97114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); 98114402Sru} 99114402Sru 100114402Srupile_box::pile_box(box *pp) : col(pp) 101114402Sru{ 102114402Sru} 103114402Sru 104114402Sruvoid pile_box::check_tabs(int level) 105114402Sru{ 106114402Sru col.list_check_tabs(level); 107114402Sru} 108114402Sru 109114402Sruvoid pile_box::debug_print() 110114402Sru{ 111114402Sru col.debug_print("pile"); 112114402Sru} 113114402Sru 114114402Sruint matrix_box::compute_metrics(int style) 115114402Sru{ 116114402Sru int i, j; 117151497Sru int max_len = 0; 118114402Sru int space = 0; 119114402Sru for (i = 0; i < len; i++) { 120114402Sru for (j = 0; j < p[i]->len; j++) 121114402Sru p[i]->p[j]->compute_metrics(style); 122151497Sru if (p[i]->len > max_len) 123151497Sru max_len = p[i]->len; 124114402Sru if (p[i]->space > space) 125114402Sru space = p[i]->space; 126114402Sru } 127114402Sru for (i = 0; i < len; i++) { 128114402Sru printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i); 129114402Sru for (j = 0; j < p[i]->len; j++) 130114402Sru printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid); 131114402Sru printf("\n"); 132114402Sru } 133114402Sru printf(".nr " WIDTH_FORMAT " %dM", 134114402Sru uid, column_sep*(len-1)+2*matrix_side_sep); 135114402Sru for (i = 0; i < len; i++) 136114402Sru printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i); 137114402Sru printf("\n"); 138114402Sru printf(".nr " BASELINE_SEP_FORMAT " %dM", 139114402Sru uid, baseline_sep+space); 140114402Sru for (i = 0; i < len; i++) 141114402Sru for (j = 1; j < p[i]->len; j++) 142114402Sru printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", 143114402Sru p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5); 144114402Sru // round it so that it's a multiple of the vertical resolution 145114402Sru printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); 146114402Sru printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" 147114402Sru "+%dM\n", 148151497Sru uid, uid, max_len-1, axis_height - shift_down); 149114402Sru printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0", 150114402Sru uid, uid); 151114402Sru for (i = 0; i < len; i++) 152114402Sru printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid); 153114402Sru printf(")>?0\n"); 154114402Sru printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n[" 155114402Sru SUP_RAISE_FORMAT "]+(0", 156151497Sru uid, uid, max_len-1, uid); 157114402Sru for (i = 0; i < len; i++) 158151497Sru if (p[i]->len == max_len) 159151497Sru printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid); 160114402Sru printf(")>?0\n"); 161114402Sru return FOUND_NOTHING; 162114402Sru} 163114402Sru 164114402Sruvoid matrix_box::output() 165114402Sru{ 166114402Sru printf("\\h'%dM'", matrix_side_sep); 167114402Sru for (int i = 0; i < len; i++) { 168114402Sru int j; 169114402Sru printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 170114402Sru for (j = 0; j < p[i]->len; j++) { 171114402Sru switch (p[i]->align) { 172114402Sru case LEFT_ALIGN: 173114402Sru break; 174114402Sru case CENTER_ALIGN: 175114402Sru printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 176114402Sru uid, i, p[i]->p[j]->uid); 177114402Sru break; 178114402Sru case RIGHT_ALIGN: 179114402Sru printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 180114402Sru uid, i, p[i]->p[j]->uid); 181114402Sru break; 182114402Sru default: 183114402Sru assert(0); 184114402Sru } 185114402Sru p[i]->p[j]->output(); 186114402Sru printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid); 187114402Sru switch (p[i]->align) { 188114402Sru case LEFT_ALIGN: 189114402Sru break; 190114402Sru case CENTER_ALIGN: 191114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'", 192114402Sru p[i]->p[j]->uid, uid, i); 193114402Sru break; 194114402Sru case RIGHT_ALIGN: 195114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'", 196114402Sru p[i]->p[j]->uid, uid, i); 197114402Sru break; 198114402Sru default: 199114402Sru assert(0); 200114402Sru } 201114402Sru if (j != p[i]->len - 1) 202114402Sru printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); 203114402Sru } 204114402Sru printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 205114402Sru printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid); 206114402Sru printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i); 207114402Sru if (i != len - 1) 208114402Sru printf("\\h'%dM'", column_sep); 209114402Sru } 210114402Sru printf("\\h'%dM'", matrix_side_sep); 211114402Sru} 212114402Sru 213114402Srumatrix_box::matrix_box(column *pp) 214114402Sru{ 215114402Sru p = new column*[10]; 216114402Sru for (int i = 0; i < 10; i++) 217114402Sru p[i] = 0; 218114402Sru maxlen = 10; 219114402Sru len = 1; 220114402Sru p[0] = pp; 221114402Sru} 222114402Sru 223114402Srumatrix_box::~matrix_box() 224114402Sru{ 225114402Sru for (int i = 0; i < len; i++) 226114402Sru delete p[i]; 227114402Sru a_delete p; 228114402Sru} 229114402Sru 230114402Sruvoid matrix_box::append(column *pp) 231114402Sru{ 232114402Sru if (len + 1 > maxlen) { 233114402Sru column **oldp = p; 234114402Sru maxlen *= 2; 235114402Sru p = new column*[maxlen]; 236114402Sru memcpy(p, oldp, sizeof(column*)*len); 237114402Sru a_delete oldp; 238114402Sru } 239114402Sru p[len++] = pp; 240114402Sru} 241114402Sru 242114402Sruvoid matrix_box::check_tabs(int level) 243114402Sru{ 244114402Sru for (int i = 0; i < len; i++) 245114402Sru p[i]->list_check_tabs(level); 246114402Sru} 247114402Sru 248114402Sruvoid matrix_box::debug_print() 249114402Sru{ 250114402Sru fprintf(stderr, "matrix { "); 251114402Sru p[0]->debug_print("col"); 252114402Sru for (int i = 1; i < len; i++) { 253114402Sru fprintf(stderr, " "); 254114402Sru p[i]->debug_print("col"); 255114402Sru } 256114402Sru fprintf(stderr, " }"); 257114402Sru} 258114402Sru 259114402Srucolumn::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0) 260114402Sru{ 261114402Sru} 262114402Sru 263114402Sruvoid column::set_alignment(alignment a) 264114402Sru{ 265114402Sru align = a; 266114402Sru} 267114402Sru 268114402Sruvoid column::set_space(int n) 269114402Sru{ 270114402Sru space = n; 271114402Sru} 272114402Sru 273114402Sruvoid column::debug_print(const char *s) 274114402Sru{ 275114402Sru char c = '\0'; // shut up -Wall 276114402Sru switch (align) { 277114402Sru case LEFT_ALIGN: 278114402Sru c = 'l'; 279114402Sru break; 280114402Sru case RIGHT_ALIGN: 281114402Sru c = 'r'; 282114402Sru break; 283114402Sru case CENTER_ALIGN: 284114402Sru c = 'c'; 285114402Sru break; 286114402Sru default: 287114402Sru assert(0); 288114402Sru } 289114402Sru fprintf(stderr, "%c%s %d { ", c, s, space); 290114402Sru list_debug_print(" above "); 291114402Sru fprintf(stderr, " }"); 292114402Sru} 293114402Sru 294