1// -*- C++ -*- 2/* Copyright (C) 1989, 1990, 1991, 1992, 2004 Free Software Foundation, Inc. 3 Written by James Clark (jjc@jclark.com) 4 5This file is part of groff. 6 7groff is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12groff is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License along 18with groff; see the file COPYING. If not, write to the Free Software 19Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 20// piles and matrices 21 22#include "eqn.h" 23#include "pbox.h" 24 25// SUP_RAISE_FORMAT gives the first baseline 26// BASELINE_SEP_FORMAT gives the separation between baselines 27 28int pile_box::compute_metrics(int style) 29{ 30 int i; 31 for (i = 0; i < col.len; i++) 32 col.p[i]->compute_metrics(style); 33 printf(".nr " WIDTH_FORMAT " 0", uid); 34 for (i = 0; i < col.len; i++) 35 printf(">?\\n[" WIDTH_FORMAT "]", col.p[i]->uid); 36 printf("\n"); 37 printf(".nr " BASELINE_SEP_FORMAT " %dM", 38 uid, baseline_sep+col.space); 39 for (i = 1; i < col.len; i++) 40 printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", 41 col.p[i-1]->uid, col.p[i]->uid, default_rule_thickness*5); 42 // round it so that it's a multiple of the vertical resolution 43 printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); 44 45 printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" 46 "+%dM\n", 47 uid, uid, col.len-1, axis_height - shift_down); 48 printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" 49 HEIGHT_FORMAT "]\n", 50 uid, uid, col.p[0]->uid); 51 printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d+\\n[" 52 DEPTH_FORMAT "]-\\n[" SUP_RAISE_FORMAT "]\n", 53 uid, uid, col.len-1, col.p[col.len-1]->uid, uid); 54 return FOUND_NOTHING; 55} 56 57void pile_box::output() 58{ 59 int i; 60 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 61 for (i = 0; i < col.len; i++) { 62 switch (col.align) { 63 case LEFT_ALIGN: 64 break; 65 case CENTER_ALIGN: 66 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 67 uid, col.p[i]->uid); 68 break; 69 case RIGHT_ALIGN: 70 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 71 uid, col.p[i]->uid); 72 break; 73 default: 74 assert(0); 75 } 76 col.p[i]->output(); 77 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", col.p[i]->uid); 78 switch (col.align) { 79 case LEFT_ALIGN: 80 break; 81 case CENTER_ALIGN: 82 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 83 col.p[i]->uid, uid); 84 break; 85 case RIGHT_ALIGN: 86 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 87 col.p[i]->uid, uid); 88 break; 89 default: 90 assert(0); 91 } 92 if (i != col.len - 1) 93 printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); 94 } 95 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 96 printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", col.len - 1, uid); 97 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); 98} 99 100pile_box::pile_box(box *pp) : col(pp) 101{ 102} 103 104void pile_box::check_tabs(int level) 105{ 106 col.list_check_tabs(level); 107} 108 109void pile_box::debug_print() 110{ 111 col.debug_print("pile"); 112} 113 114int matrix_box::compute_metrics(int style) 115{ 116 int i, j; 117 int max_len = 0; 118 int space = 0; 119 for (i = 0; i < len; i++) { 120 for (j = 0; j < p[i]->len; j++) 121 p[i]->p[j]->compute_metrics(style); 122 if (p[i]->len > max_len) 123 max_len = p[i]->len; 124 if (p[i]->space > space) 125 space = p[i]->space; 126 } 127 for (i = 0; i < len; i++) { 128 printf(".nr " COLUMN_WIDTH_FORMAT " 0", uid, i); 129 for (j = 0; j < p[i]->len; j++) 130 printf(">?\\n[" WIDTH_FORMAT "]", p[i]->p[j]->uid); 131 printf("\n"); 132 } 133 printf(".nr " WIDTH_FORMAT " %dM", 134 uid, column_sep*(len-1)+2*matrix_side_sep); 135 for (i = 0; i < len; i++) 136 printf("+\\n[" COLUMN_WIDTH_FORMAT "]", uid, i); 137 printf("\n"); 138 printf(".nr " BASELINE_SEP_FORMAT " %dM", 139 uid, baseline_sep+space); 140 for (i = 0; i < len; i++) 141 for (j = 1; j < p[i]->len; j++) 142 printf(">?(\\n[" DEPTH_FORMAT "]+\\n[" HEIGHT_FORMAT "]+%dM)", 143 p[i]->p[j-1]->uid, p[i]->p[j]->uid, default_rule_thickness*5); 144 // round it so that it's a multiple of the vertical resolution 145 printf("/\\n(.V+(\\n(.V/2)*\\n(.V\n"); 146 printf(".nr " SUP_RAISE_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d/2" 147 "+%dM\n", 148 uid, uid, max_len-1, axis_height - shift_down); 149 printf(".nr " HEIGHT_FORMAT " 0\\n[" SUP_RAISE_FORMAT "]+(0", 150 uid, uid); 151 for (i = 0; i < len; i++) 152 printf(">?\\n[" HEIGHT_FORMAT "]", p[i]->p[0]->uid); 153 printf(")>?0\n"); 154 printf(".nr " DEPTH_FORMAT " \\n[" BASELINE_SEP_FORMAT "]*%d-\\n[" 155 SUP_RAISE_FORMAT "]+(0", 156 uid, uid, max_len-1, uid); 157 for (i = 0; i < len; i++) 158 if (p[i]->len == max_len) 159 printf(">?\\n[" DEPTH_FORMAT "]", p[i]->p[max_len-1]->uid); 160 printf(")>?0\n"); 161 return FOUND_NOTHING; 162} 163 164void matrix_box::output() 165{ 166 printf("\\h'%dM'", matrix_side_sep); 167 for (int i = 0; i < len; i++) { 168 int j; 169 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 170 for (j = 0; j < p[i]->len; j++) { 171 switch (p[i]->align) { 172 case LEFT_ALIGN: 173 break; 174 case CENTER_ALIGN: 175 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 176 uid, i, p[i]->p[j]->uid); 177 break; 178 case RIGHT_ALIGN: 179 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 180 uid, i, p[i]->p[j]->uid); 181 break; 182 default: 183 assert(0); 184 } 185 p[i]->p[j]->output(); 186 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p[i]->p[j]->uid); 187 switch (p[i]->align) { 188 case LEFT_ALIGN: 189 break; 190 case CENTER_ALIGN: 191 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u/2u'", 192 p[i]->p[j]->uid, uid, i); 193 break; 194 case RIGHT_ALIGN: 195 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" COLUMN_WIDTH_FORMAT "]u'", 196 p[i]->p[j]->uid, uid, i); 197 break; 198 default: 199 assert(0); 200 } 201 if (j != p[i]->len - 1) 202 printf("\\v'\\n[" BASELINE_SEP_FORMAT "]u'", uid); 203 } 204 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 205 printf("\\v'-(%du*\\n[" BASELINE_SEP_FORMAT "]u)'", p[i]->len - 1, uid); 206 printf("\\h'\\n[" COLUMN_WIDTH_FORMAT "]u'", uid, i); 207 if (i != len - 1) 208 printf("\\h'%dM'", column_sep); 209 } 210 printf("\\h'%dM'", matrix_side_sep); 211} 212 213matrix_box::matrix_box(column *pp) 214{ 215 p = new column*[10]; 216 for (int i = 0; i < 10; i++) 217 p[i] = 0; 218 maxlen = 10; 219 len = 1; 220 p[0] = pp; 221} 222 223matrix_box::~matrix_box() 224{ 225 for (int i = 0; i < len; i++) 226 delete p[i]; 227 a_delete p; 228} 229 230void matrix_box::append(column *pp) 231{ 232 if (len + 1 > maxlen) { 233 column **oldp = p; 234 maxlen *= 2; 235 p = new column*[maxlen]; 236 memcpy(p, oldp, sizeof(column*)*len); 237 a_delete oldp; 238 } 239 p[len++] = pp; 240} 241 242void matrix_box::check_tabs(int level) 243{ 244 for (int i = 0; i < len; i++) 245 p[i]->list_check_tabs(level); 246} 247 248void matrix_box::debug_print() 249{ 250 fprintf(stderr, "matrix { "); 251 p[0]->debug_print("col"); 252 for (int i = 1; i < len; i++) { 253 fprintf(stderr, " "); 254 p[i]->debug_print("col"); 255 } 256 fprintf(stderr, " }"); 257} 258 259column::column(box *pp) : box_list(pp), align(CENTER_ALIGN), space(0) 260{ 261} 262 263void column::set_alignment(alignment a) 264{ 265 align = a; 266} 267 268void column::set_space(int n) 269{ 270 space = n; 271} 272 273void column::debug_print(const char *s) 274{ 275 char c = '\0'; // shut up -Wall 276 switch (align) { 277 case LEFT_ALIGN: 278 c = 'l'; 279 break; 280 case RIGHT_ALIGN: 281 c = 'r'; 282 break; 283 case CENTER_ALIGN: 284 c = 'c'; 285 break; 286 default: 287 assert(0); 288 } 289 fprintf(stderr, "%c%s %d { ", c, s, space); 290 list_debug_print(" above "); 291 fprintf(stderr, " }"); 292} 293 294