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