1114402Sru// -*- C++ -*- 2114402Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2001, 2002 3114402Sru Free Software Foundation, Inc. 4114402Sru Written by James Clark (jjc@jclark.com) 5114402Sru 6114402SruThis file is part of groff. 7114402Sru 8114402Srugroff is free software; you can redistribute it and/or modify it under 9114402Sruthe terms of the GNU General Public License as published by the Free 10114402SruSoftware Foundation; either version 2, or (at your option) any later 11114402Sruversion. 12114402Sru 13114402Srugroff is distributed in the hope that it will be useful, but WITHOUT ANY 14114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 15114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16114402Srufor more details. 17114402Sru 18114402SruYou should have received a copy of the GNU General Public License along 19114402Sruwith groff; see the file COPYING. If not, write to the Free Software 20151497SruFoundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 21114402Sru 22114402Sru#include "eqn.h" 23114402Sru#include "pbox.h" 24114402Sru 25114402Sruclass over_box : public box { 26114402Sruprivate: 27114402Sru int reduce_size; 28114402Sru box *num; 29114402Sru box *den; 30114402Srupublic: 31114402Sru over_box(int small, box *, box *); 32114402Sru ~over_box(); 33114402Sru void debug_print(); 34114402Sru int compute_metrics(int); 35114402Sru void output(); 36114402Sru void check_tabs(int); 37114402Sru}; 38114402Sru 39114402Srubox *make_over_box(box *pp, box *qq) 40114402Sru{ 41114402Sru return new over_box(0, pp, qq); 42114402Sru} 43114402Sru 44114402Srubox *make_small_over_box(box *pp, box *qq) 45114402Sru{ 46114402Sru return new over_box(1, pp, qq); 47114402Sru} 48114402Sru 49114402Sruover_box::over_box(int is_small, box *pp, box *qq) 50114402Sru: reduce_size(is_small), num(pp), den(qq) 51114402Sru{ 52114402Sru spacing_type = INNER_TYPE; 53114402Sru} 54114402Sru 55114402Sruover_box::~over_box() 56114402Sru{ 57114402Sru delete num; 58114402Sru delete den; 59114402Sru} 60114402Sru 61114402Sruint over_box::compute_metrics(int style) 62114402Sru{ 63114402Sru if (reduce_size) { 64114402Sru style = script_style(style); 65114402Sru printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); 66114402Sru set_script_size(); 67114402Sru printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); 68114402Sru } 69114402Sru int mark_uid = 0; 70114402Sru int res = num->compute_metrics(style); 71114402Sru if (res) 72114402Sru mark_uid = num->uid; 73114402Sru int r = den->compute_metrics(cramped_style(style)); 74114402Sru if (r && res) 75114402Sru error("multiple marks and lineups"); 76114402Sru else { 77114402Sru mark_uid = den->uid; 78114402Sru res = r; 79114402Sru } 80114402Sru if (reduce_size) 81114402Sru printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); 82114402Sru printf(".nr " WIDTH_FORMAT " (\\n[" WIDTH_FORMAT "]>?\\n[" WIDTH_FORMAT "]", 83114402Sru uid, num->uid, den->uid); 84114402Sru // allow for \(ru being wider than both the numerator and denominator 85114402Sru if (!draw_flag) 86114402Sru fputs(">?\\w" DELIMITER_CHAR "\\(ru" DELIMITER_CHAR, stdout); 87114402Sru printf(")+%dM\n", null_delimiter_space*2 + over_hang*2); 88114402Sru // 15b 89114402Sru printf(".nr " SUP_RAISE_FORMAT " %dM\n", 90114402Sru uid, (reduce_size ? num2 : num1)); 91114402Sru printf(".nr " SUB_LOWER_FORMAT " %dM\n", 92114402Sru uid, (reduce_size ? denom2 : denom1)); 93114402Sru 94114402Sru // 15d 95114402Sru printf(".nr " SUP_RAISE_FORMAT " +(\\n[" DEPTH_FORMAT 96114402Sru "]-\\n[" SUP_RAISE_FORMAT "]+%dM+(%dM/2)+%dM)>?0\n", 97114402Sru uid, num->uid, uid, axis_height, default_rule_thickness, 98114402Sru default_rule_thickness*(reduce_size ? 1 : 3)); 99114402Sru printf(".nr " SUB_LOWER_FORMAT " +(\\n[" HEIGHT_FORMAT 100114402Sru "]-\\n[" SUB_LOWER_FORMAT "]-%dM+(%dM/2)+%dM)>?0\n", 101114402Sru uid, den->uid, uid, axis_height, default_rule_thickness, 102114402Sru default_rule_thickness*(reduce_size ? 1 : 3)); 103114402Sru 104114402Sru 105114402Sru printf(".nr " HEIGHT_FORMAT " \\n[" SUP_RAISE_FORMAT "]+\\n[" 106114402Sru HEIGHT_FORMAT "]\n", 107114402Sru uid, uid, num->uid); 108114402Sru printf(".nr " DEPTH_FORMAT " \\n[" SUB_LOWER_FORMAT "]+\\n[" 109114402Sru DEPTH_FORMAT "]\n", 110114402Sru uid, uid, den->uid); 111114402Sru if (res) 112114402Sru printf(".nr " MARK_REG " +(\\n[" WIDTH_FORMAT "]-\\n[" 113114402Sru WIDTH_FORMAT "]/2)\n", uid, mark_uid); 114114402Sru return res; 115114402Sru} 116114402Sru 117114402Sru#define USE_Z 118114402Sru 119114402Sruvoid over_box::output() 120114402Sru{ 121114402Sru if (reduce_size) 122114402Sru printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 123114402Sru#ifdef USE_Z 124114402Sru printf("\\Z" DELIMITER_CHAR); 125114402Sru#endif 126114402Sru // move up to the numerator baseline 127114402Sru printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 128114402Sru // move across so that it's centered 129114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 130114402Sru uid, num->uid); 131114402Sru 132114402Sru // print the numerator 133114402Sru num->output(); 134114402Sru 135114402Sru#ifdef USE_Z 136114402Sru printf(DELIMITER_CHAR); 137114402Sru#else 138114402Sru // back again 139114402Sru printf("\\h'-\\n[" WIDTH_FORMAT "]u'", num->uid); 140114402Sru printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", 141114402Sru uid, num->uid); 142114402Sru // down again 143114402Sru printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 144114402Sru#endif 145114402Sru#ifdef USE_Z 146114402Sru printf("\\Z" DELIMITER_CHAR); 147114402Sru#endif 148114402Sru // move down to the denominator baseline 149114402Sru printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); 150114402Sru 151114402Sru // move across so that it's centered 152114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u'", 153114402Sru uid, den->uid); 154114402Sru 155114402Sru // print the the denominator 156114402Sru den->output(); 157114402Sru 158114402Sru#ifdef USE_Z 159114402Sru printf(DELIMITER_CHAR); 160114402Sru#else 161114402Sru // back again 162114402Sru printf("\\h'-\\n[" WIDTH_FORMAT "]u'", den->uid); 163114402Sru printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u)'", 164114402Sru uid, den->uid); 165114402Sru // up again 166114402Sru printf("\\v'-\\n[" SUB_LOWER_FORMAT "]u'", uid); 167114402Sru#endif 168114402Sru if (reduce_size) 169114402Sru printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 170114402Sru // draw the line 171114402Sru printf("\\h'%dM'", null_delimiter_space); 172114402Sru printf("\\v'-%dM'", axis_height); 173114402Sru fputs(draw_flag ? "\\D'l" : "\\l'", stdout); 174114402Sru printf("\\n[" WIDTH_FORMAT "]u-%dM", 175114402Sru uid, 2*null_delimiter_space); 176114402Sru fputs(draw_flag ? " 0'" : "\\&\\(ru'", stdout); 177114402Sru printf("\\v'%dM'", axis_height); 178114402Sru printf("\\h'%dM'", null_delimiter_space); 179114402Sru} 180114402Sru 181114402Sruvoid over_box::debug_print() 182114402Sru{ 183114402Sru fprintf(stderr, "{ "); 184114402Sru num->debug_print(); 185114402Sru if (reduce_size) 186114402Sru fprintf(stderr, " } smallover { "); 187114402Sru else 188114402Sru fprintf(stderr, " } over { "); 189114402Sru den->debug_print(); 190114402Sru fprintf(stderr, " }"); 191114402Sru} 192114402Sru 193114402Sruvoid over_box::check_tabs(int level) 194114402Sru{ 195114402Sru num->check_tabs(level + 1); 196114402Sru den->check_tabs(level + 1); 197114402Sru} 198