1114402Sru// -*- C++ -*- 2151497Sru/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004 3151497Sru 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 script_box : public pointer_box { 26114402Sruprivate: 27114402Sru box *sub; 28114402Sru box *sup; 29114402Srupublic: 30114402Sru script_box(box *, box *, box *); 31114402Sru ~script_box(); 32114402Sru int compute_metrics(int); 33114402Sru void output(); 34114402Sru void debug_print(); 35114402Sru int left_is_italic(); 36114402Sru void hint(unsigned); 37114402Sru void check_tabs(int); 38114402Sru}; 39114402Sru 40114402Sru/* The idea is that the script should attach to the rightmost box 41114402Sruof a list. For example, given `2x sup 3', the superscript should 42114402Sruattach to `x' rather than `2x'. */ 43114402Sru 44114402Srubox *make_script_box(box *nuc, box *sub, box *sup) 45114402Sru{ 46114402Sru list_box *b = nuc->to_list_box(); 47114402Sru if (b != 0) { 48114402Sru b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1], 49114402Sru sub, 50114402Sru sup); 51114402Sru return b; 52114402Sru } 53114402Sru else 54114402Sru return new script_box(nuc, sub, sup); 55114402Sru} 56114402Sru 57114402Sruscript_box::script_box(box *pp, box *qq, box *rr) 58114402Sru: pointer_box(pp), sub(qq), sup(rr) 59114402Sru{ 60114402Sru} 61114402Sru 62114402Sruscript_box::~script_box() 63114402Sru{ 64114402Sru delete sub; 65114402Sru delete sup; 66114402Sru} 67114402Sru 68114402Sruint script_box::left_is_italic() 69114402Sru{ 70114402Sru return p->left_is_italic(); 71114402Sru} 72114402Sru 73114402Sruint script_box::compute_metrics(int style) 74114402Sru{ 75114402Sru int res = p->compute_metrics(style); 76114402Sru p->compute_subscript_kern(); 77114402Sru printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); 78114402Sru if (!(style <= SCRIPT_STYLE && one_size_reduction_flag)) 79114402Sru set_script_size(); 80114402Sru printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); 81114402Sru if (sub != 0) 82114402Sru sub->compute_metrics(cramped_style(script_style(style))); 83114402Sru if (sup != 0) 84114402Sru sup->compute_metrics(script_style(style)); 85114402Sru // 18a 86114402Sru if (p->is_char()) { 87114402Sru printf(".nr " SUP_RAISE_FORMAT " 0\n", uid); 88114402Sru printf(".nr " SUB_LOWER_FORMAT " 0\n", uid); 89114402Sru } 90114402Sru else { 91114402Sru printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", 92114402Sru uid, p->uid, sup_drop); 93114402Sru printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n", 94114402Sru uid, p->uid, sub_drop); 95114402Sru } 96114402Sru printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); 97114402Sru if (sup == 0) { 98114402Sru assert(sub != 0); 99114402Sru // 18b 100114402Sru printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n[" 101114402Sru HEIGHT_FORMAT "]-(%dM*4/5))\n", 102114402Sru uid, uid, sub1, sub->uid, x_height); 103114402Sru } 104114402Sru else { 105114402Sru // sup != 0 106114402Sru // 18c 107151497Sru int pos; 108114402Sru if (style == DISPLAY_STYLE) 109151497Sru pos = sup1; 110114402Sru else if (style & 1) // not cramped 111151497Sru pos = sup2; 112114402Sru else 113151497Sru pos = sup3; 114114402Sru printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT 115114402Sru "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n", 116151497Sru uid, uid, pos, sup->uid, x_height); 117114402Sru // 18d 118114402Sru if (sub != 0) { 119114402Sru printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n", 120151497Sru uid, uid, sub2); 121114402Sru // 18e 122114402Sru printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n[" 123114402Sru SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n[" 124114402Sru SUB_LOWER_FORMAT "]+(4*%dM)\n", 125114402Sru sup->uid, uid, sub->uid, uid, default_rule_thickness); 126114402Sru printf(".if \\n[" TEMP_REG "] \\{"); 127114402Sru printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid); 128114402Sru printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT 129114402Sru "]+\\n[" DEPTH_FORMAT "]>?0\n", 130114402Sru x_height, uid, sup->uid); 131114402Sru printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid); 132114402Sru printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid); 133114402Sru printf(".\\}\n"); 134114402Sru } 135114402Sru } 136114402Sru printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid); 137114402Sru if (sub != 0 && sup != 0) 138114402Sru printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n[" 139114402Sru WIDTH_FORMAT "])+%dM)>?0\n", 140114402Sru sub->uid, p->uid, sup->uid, script_space); 141114402Sru else if (sub != 0) 142114402Sru printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n", 143114402Sru sub->uid, p->uid, script_space); 144114402Sru else if (sup != 0) 145114402Sru printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space); 146114402Sru else 147114402Sru printf("\n"); 148114402Sru printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]", 149114402Sru uid, p->uid); 150114402Sru if (sup != 0) 151114402Sru printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])", 152114402Sru uid, sup->uid); 153114402Sru if (sub != 0) 154114402Sru printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])", 155114402Sru uid, sub->uid); 156114402Sru printf("\n"); 157114402Sru printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]", 158114402Sru uid, p->uid); 159114402Sru if (sub != 0) 160114402Sru printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])", 161114402Sru uid, sub->uid); 162114402Sru if (sup != 0) 163114402Sru printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])", 164114402Sru uid, sup->uid); 165114402Sru printf("\n"); 166114402Sru return res; 167114402Sru} 168114402Sru 169114402Sruvoid script_box::output() 170114402Sru{ 171114402Sru p->output(); 172114402Sru if (sup != 0) { 173114402Sru printf("\\Z" DELIMITER_CHAR); 174114402Sru printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 175114402Sru printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 176114402Sru sup->output(); 177114402Sru printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 178114402Sru printf(DELIMITER_CHAR); 179114402Sru } 180114402Sru if (sub != 0) { 181114402Sru printf("\\Z" DELIMITER_CHAR); 182114402Sru printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); 183114402Sru printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 184114402Sru printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid); 185114402Sru sub->output(); 186114402Sru printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 187114402Sru printf(DELIMITER_CHAR); 188114402Sru } 189114402Sru printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 190114402Sru uid, p->uid); 191114402Sru} 192114402Sru 193114402Sruvoid script_box::hint(unsigned flags) 194114402Sru{ 195114402Sru p->hint(flags & ~HINT_NEXT_IS_ITALIC); 196114402Sru} 197114402Sru 198114402Sruvoid script_box::debug_print() 199114402Sru{ 200114402Sru fprintf(stderr, "{ "); 201114402Sru p->debug_print(); 202114402Sru fprintf(stderr, " }"); 203114402Sru if (sub) { 204114402Sru fprintf(stderr, " sub { "); 205114402Sru sub->debug_print(); 206114402Sru fprintf(stderr, " }"); 207114402Sru } 208114402Sru if (sup) { 209114402Sru fprintf(stderr, " sup { "); 210114402Sru sup->debug_print(); 211114402Sru fprintf(stderr, " }"); 212114402Sru } 213114402Sru} 214114402Sru 215114402Sruvoid script_box::check_tabs(int level) 216114402Sru{ 217114402Sru if (sup) 218114402Sru sup->check_tabs(level + 1); 219114402Sru if (sub) 220114402Sru sub->check_tabs(level + 1); 221114402Sru p->check_tabs(level); 222114402Sru} 223