1/* $NetBSD$ */ 2 3// -*- C++ -*- 4/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002 5 Free Software Foundation, Inc. 6 Written by James Clark (jjc@jclark.com) 7 8This file is part of groff. 9 10groff is free software; you can redistribute it and/or modify it under 11the terms of the GNU General Public License as published by the Free 12Software Foundation; either version 2, or (at your option) any later 13version. 14 15groff is distributed in the hope that it will be useful, but WITHOUT ANY 16WARRANTY; without even the implied warranty of MERCHANTABILITY or 17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18for more details. 19 20You should have received a copy of the GNU General Public License along 21with groff; see the file COPYING. If not, write to the Free Software 22Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 23 24#include "eqn.h" 25#include "pbox.h" 26 27class over_box : public box { 28private: 29 int reduce_size; 30 box *num; 31 box *den; 32public: 33 over_box(int small, box *, box *); 34 ~over_box(); 35 void debug_print(); 36 int compute_metrics(int); 37 void output(); 38 void check_tabs(int); 39}; 40 41box *make_over_box(box *pp, box *qq) 42{ 43 return new over_box(0, pp, qq); 44} 45 46box *make_small_over_box(box *pp, box *qq) 47{ 48 return new over_box(1, pp, qq); 49} 50 51over_box::over_box(int is_small, box *pp, box *qq) 52: reduce_size(is_small), num(pp), den(qq) 53{ 54 spacing_type = INNER_TYPE; 55} 56 57over_box::~over_box() 58{ 59 delete num; 60 delete den; 61} 62 63int over_box::compute_metrics(int style) 64{ 65 if (reduce_size) { 66 style = script_style(style); 67 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); 68 set_script_size(); 69 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); 70 } 71 int mark_uid = 0; 72 int res = num->compute_metrics(style); 73 if (res) 74 mark_uid = num->uid; 75 int r = den->compute_metrics(cramped_style(style)); 76 if (r && res) 77 error("multiple marks and lineups"); 78 else { 79 mark_uid = den->uid; 80 res = r; 81 } 82 if (reduce_size) 83 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); 84 printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]", 85 uid, num->uid, den->uid); 86 // allow for \(ru being wider than both the numerator and denominator 87 if (!draw_flag) 88 fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout); 89 printf(")+%dM\n", null_delimiter_space*2 + over_hang*2); 90 // 15b 91 printf(".nr " SUP_RAISE_FORMAT " %dM\n", 92 uid, (reduce_size ? num2 : num1)); 93 printf(".nr " SUB_LOWER_FORMAT " %dM\n", 94 uid, (reduce_size ? denom2 : denom1)); 95 96 // 15d 97 printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT 98 "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n", 99 uid, num->uid, uid, axis_height, default_rule_thickness, 100 default_rule_thickness*(reduce_size ? 1 : 3)); 101 printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT 102 "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n", 103 uid, den->uid, uid, axis_height, default_rule_thickness, 104 default_rule_thickness*(reduce_size ? 1 : 3)); 105 106 107 printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" 108 HEIGHT_FORMAT "]\n", 109 uid, uid, num->uid); 110 printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n[" 111 DEPTH_FORMAT "]\n", 112 uid, uid, den->uid); 113 if (res) 114 printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n[" 115 WIDTH_FORMAT "]/2)\n", uid, mark_uid); 116 return res; 117} 118 119#define USE_Z 120 121void over_box::output() 122{ 123 if (reduce_size) 124 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 125#ifdef USE_Z 126 printf("\\Z" DELIMITER_CHAR); 127#endif 128 // move up to the numerator baseline 129 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 130 // move across so that it's centered 131 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 132 uid, num->uid); 133 134 // print the numerator 135 num->output(); 136 137#ifdef USE_Z 138 printf(DELIMITER_CHAR); 139#else 140 // back again 141 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid); 142 printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", 143 uid, num->uid); 144 // down again 145 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 146#endif 147#ifdef USE_Z 148 printf("\\Z" DELIMITER_CHAR); 149#endif 150 // move down to the denominator baseline 151 printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); 152 153 // move across so that it's centered 154 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 155 uid, den->uid); 156 157 // print the the denominator 158 den->output(); 159 160#ifdef USE_Z 161 printf(DELIMITER_CHAR); 162#else 163 // back again 164 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid); 165 printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", 166 uid, den->uid); 167 // up again 168 printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid); 169#endif 170 if (reduce_size) 171 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 172 // draw the line 173 printf("\\h'%dM'", null_delimiter_space); 174 printf("\\v'-%dM'", axis_height); 175 fputs(draw_flag ? "\\D'l" : "\\l'", stdout); 176 printf("\\n[" WIDTH_FORMAT "]u-%dM", 177 uid, 2*null_delimiter_space); 178 fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout); 179 printf("\\v'%dM'", axis_height); 180 printf("\\h'%dM'", null_delimiter_space); 181} 182 183void over_box::debug_print() 184{ 185 fprintf(stderr, "{ "); 186 num->debug_print(); 187 if (reduce_size) 188 fprintf(stderr, " } smallover { "); 189 else 190 fprintf(stderr, " } over { "); 191 den->debug_print(); 192 fprintf(stderr, " }"); 193} 194 195void over_box::check_tabs(int level) 196{ 197 num->check_tabs(level + 1); 198 den->check_tabs(level + 1); 199} 200