1178456Sgnn/* $NetBSD$ */ 2178456Sgnn 3178456Sgnn// -*- C++ -*- 4178456Sgnn/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc. 5178456Sgnn Written by James Clark (jjc@jclark.com) 6178456Sgnn 7178456SgnnThis file is part of groff. 8178456Sgnn 9178456Sgnngroff is free software; you can redistribute it and/or modify it under 10213327Sgnnthe terms of the GNU General Public License as published by the Free 11213327SgnnSoftware Foundation; either version 2, or (at your option) any later 12178456Sgnnversion. 13178456Sgnn 14213327Sgnngroff is distributed in the hope that it will be useful, but WITHOUT ANY 15178456SgnnWARRANTY; without even the implied warranty of MERCHANTABILITY or 16178456SgnnFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17178456Sgnnfor more details. 18178456Sgnn 19213327SgnnYou should have received a copy of the GNU General Public License along 20178456Sgnnwith groff; see the file COPYING. If not, write to the Free Software 21178456SgnnFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 22213327Sgnn 23178456Sgnn#include "eqn.h" 24178456Sgnn#include "pbox.h" 25178456Sgnn 26178456Sgnnclass limit_box : public box { 27178456Sgnnprivate: 28178456Sgnn box *p; 29178456Sgnn box *from; 30178456Sgnn box *to; 31178456Sgnnpublic: 32178456Sgnn limit_box(box *, box *, box *); 33178456Sgnn ~limit_box(); 34178456Sgnn int compute_metrics(int); 35178456Sgnn void output(); 36178456Sgnn void debug_print(); 37178456Sgnn void check_tabs(int); 38178456Sgnn}; 39178456Sgnn 40178456Sgnnbox *make_limit_box(box *pp, box *qq, box *rr) 41178456Sgnn{ 42178456Sgnn return new limit_box(pp, qq, rr); 43213327Sgnn} 44213327Sgnn 45178456Sgnnlimit_box::limit_box(box *pp, box *qq, box *rr) 46213327Sgnn: p(pp), from(qq), to(rr) 47213327Sgnn{ 48213327Sgnn spacing_type = p->spacing_type; 49179528Sgnn} 50179528Sgnn 51179528Sgnnlimit_box::~limit_box() 52178456Sgnn{ 53178456Sgnn delete p; 54178456Sgnn delete from; 55178456Sgnn delete to; 56178456Sgnn} 57178456Sgnn 58178456Sgnnint limit_box::compute_metrics(int style) 59178456Sgnn{ 60178456Sgnn printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); 61178456Sgnn if (!(style <= SCRIPT_STYLE && one_size_reduction_flag)) 62178456Sgnn set_script_size(); 63178456Sgnn printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); 64178456Sgnn int res = 0; 65178456Sgnn int mark_uid = -1; 66213327Sgnn if (from != 0) { 67178456Sgnn res = from->compute_metrics(cramped_style(script_style(style))); 68178456Sgnn if (res) 69178456Sgnn mark_uid = from->uid; 70178456Sgnn } 71178456Sgnn if (to != 0) { 72178456Sgnn int r = to->compute_metrics(script_style(style)); 73178456Sgnn if (res && r) 74213327Sgnn error("multiple marks and lineups"); 75 else { 76 mark_uid = to->uid; 77 res = r; 78 } 79 } 80 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); 81 int r = p->compute_metrics(style); 82 p->compute_subscript_kern(); 83 if (res && r) 84 error("multiple marks and lineups"); 85 else { 86 mark_uid = p->uid; 87 res = r; 88 } 89 printf(".nr " LEFT_WIDTH_FORMAT " " 90 "0\\n[" WIDTH_FORMAT "]", 91 uid, p->uid); 92 if (from != 0) 93 printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", 94 p->uid, from->uid); 95 if (to != 0) 96 printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", 97 p->uid, to->uid); 98 printf("/2\n"); 99 printf(".nr " WIDTH_FORMAT " " 100 "0\\n[" WIDTH_FORMAT "]", 101 uid, p->uid); 102 if (from != 0) 103 printf(">?(-\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", 104 p->uid, from->uid); 105 if (to != 0) 106 printf(">?(\\n[" SUB_KERN_FORMAT "]+\\n[" WIDTH_FORMAT "])", 107 p->uid, to->uid); 108 printf("/2+\\n[" LEFT_WIDTH_FORMAT "]\n", uid); 109 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid); 110 if (to != 0) 111 printf(">?\\n[" WIDTH_FORMAT "]", to->uid); 112 if (from != 0) 113 printf(">?\\n[" WIDTH_FORMAT "]", from->uid); 114 printf("\n"); 115 if (res) 116 printf(".nr " MARK_REG " +(\\n[" LEFT_WIDTH_FORMAT "]" 117 "-(\\n[" WIDTH_FORMAT "]/2))\n", 118 uid, mark_uid); 119 if (to != 0) { 120 printf(".nr " SUP_RAISE_FORMAT " %dM+\\n[" DEPTH_FORMAT 121 "]>?%dM+\\n[" HEIGHT_FORMAT "]\n", 122 uid, big_op_spacing1, to->uid, big_op_spacing3, p->uid); 123 printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" 124 HEIGHT_FORMAT "]+%dM\n", 125 uid, uid, to->uid, big_op_spacing5); 126 } 127 else 128 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 129 if (from != 0) { 130 printf(".nr " SUB_LOWER_FORMAT " %dM+\\n[" HEIGHT_FORMAT 131 "]>?%dM+\\n[" DEPTH_FORMAT "]\n", 132 uid, big_op_spacing2, from->uid, big_op_spacing4, p->uid); 133 printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n[" 134 DEPTH_FORMAT "]+%dM\n", 135 uid, uid, from->uid, big_op_spacing5); 136 } 137 else 138 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 139 return res; 140} 141 142void limit_box::output() 143{ 144 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 145 if (to != 0) { 146 printf("\\Z" DELIMITER_CHAR); 147 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 148 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" 149 "+(-\\n[" WIDTH_FORMAT "]u+\\n[" SUB_KERN_FORMAT "]u/2u)'", 150 uid, to->uid, p->uid); 151 to->output(); 152 printf(DELIMITER_CHAR); 153 } 154 if (from != 0) { 155 printf("\\Z" DELIMITER_CHAR); 156 printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); 157 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" 158 "+(-\\n[" SUB_KERN_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", 159 uid, p->uid, from->uid); 160 from->output(); 161 printf(DELIMITER_CHAR); 162 } 163 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 164 printf("\\Z" DELIMITER_CHAR); 165 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u" 166 "-(\\n[" WIDTH_FORMAT "]u/2u)'", 167 uid, p->uid); 168 p->output(); 169 printf(DELIMITER_CHAR); 170 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); 171} 172 173void limit_box::debug_print() 174{ 175 fprintf(stderr, "{ "); 176 p->debug_print(); 177 fprintf(stderr, " }"); 178 if (from) { 179 fprintf(stderr, " from { "); 180 from->debug_print(); 181 fprintf(stderr, " }"); 182 } 183 if (to) { 184 fprintf(stderr, " to { "); 185 to->debug_print(); 186 fprintf(stderr, " }"); 187 } 188} 189 190void limit_box::check_tabs(int level) 191{ 192 if (to) 193 to->check_tabs(level + 1); 194 if (from) 195 from->check_tabs(level + 1); 196 p->check_tabs(level + 1); 197} 198