1// -*- C++ -*- 2/* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2004 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 script_box : public pointer_box { 26private: 27 box *sub; 28 box *sup; 29public: 30 script_box(box *, box *, box *); 31 ~script_box(); 32 int compute_metrics(int); 33 void output(); 34 void debug_print(); 35 int left_is_italic(); 36 void hint(unsigned); 37 void check_tabs(int); 38}; 39 40/* The idea is that the script should attach to the rightmost box 41of a list. For example, given `2x sup 3', the superscript should 42attach to `x' rather than `2x'. */ 43 44box *make_script_box(box *nuc, box *sub, box *sup) 45{ 46 list_box *b = nuc->to_list_box(); 47 if (b != 0) { 48 b->list.p[b->list.len-1] = make_script_box(b->list.p[b->list.len - 1], 49 sub, 50 sup); 51 return b; 52 } 53 else 54 return new script_box(nuc, sub, sup); 55} 56 57script_box::script_box(box *pp, box *qq, box *rr) 58: pointer_box(pp), sub(qq), sup(rr) 59{ 60} 61 62script_box::~script_box() 63{ 64 delete sub; 65 delete sup; 66} 67 68int script_box::left_is_italic() 69{ 70 return p->left_is_italic(); 71} 72 73int script_box::compute_metrics(int style) 74{ 75 int res = p->compute_metrics(style); 76 p->compute_subscript_kern(); 77 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); 78 if (!(style <= SCRIPT_STYLE && one_size_reduction_flag)) 79 set_script_size(); 80 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); 81 if (sub != 0) 82 sub->compute_metrics(cramped_style(script_style(style))); 83 if (sup != 0) 84 sup->compute_metrics(script_style(style)); 85 // 18a 86 if (p->is_char()) { 87 printf(".nr " SUP_RAISE_FORMAT " 0\n", uid); 88 printf(".nr " SUB_LOWER_FORMAT " 0\n", uid); 89 } 90 else { 91 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", 92 uid, p->uid, sup_drop); 93 printf(".nr " SUB_LOWER_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n", 94 uid, p->uid, sub_drop); 95 } 96 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); 97 if (sup == 0) { 98 assert(sub != 0); 99 // 18b 100 printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM>?(\\n[" 101 HEIGHT_FORMAT "]-(%dM*4/5))\n", 102 uid, uid, sub1, sub->uid, x_height); 103 } 104 else { 105 // sup != 0 106 // 18c 107 int pos; 108 if (style == DISPLAY_STYLE) 109 pos = sup1; 110 else if (style & 1) // not cramped 111 pos = sup2; 112 else 113 pos = sup3; 114 printf(".nr " SUP_RAISE_FORMAT " \\n[" SUP_RAISE_FORMAT 115 "]>?%dM>?(\\n[" DEPTH_FORMAT "]+(%dM/4))\n", 116 uid, uid, pos, sup->uid, x_height); 117 // 18d 118 if (sub != 0) { 119 printf(".nr " SUB_LOWER_FORMAT " \\n[" SUB_LOWER_FORMAT "]>?%dM\n", 120 uid, uid, sub2); 121 // 18e 122 printf(".nr " TEMP_REG " \\n[" DEPTH_FORMAT "]-\\n[" 123 SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "]-\\n[" 124 SUB_LOWER_FORMAT "]+(4*%dM)\n", 125 sup->uid, uid, sub->uid, uid, default_rule_thickness); 126 printf(".if \\n[" TEMP_REG "] \\{"); 127 printf(".nr " SUB_LOWER_FORMAT " +\\n[" TEMP_REG "]\n", uid); 128 printf(".nr " TEMP_REG " (%dM*4/5)-\\n[" SUP_RAISE_FORMAT 129 "]+\\n[" DEPTH_FORMAT "]>?0\n", 130 x_height, uid, sup->uid); 131 printf(".nr " SUP_RAISE_FORMAT " +\\n[" TEMP_REG "]\n", uid); 132 printf(".nr " SUB_LOWER_FORMAT " -\\n[" TEMP_REG "]\n", uid); 133 printf(".\\}\n"); 134 } 135 } 136 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]", uid, p->uid); 137 if (sub != 0 && sup != 0) 138 printf("+((\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]>?\\n[" 139 WIDTH_FORMAT "])+%dM)>?0\n", 140 sub->uid, p->uid, sup->uid, script_space); 141 else if (sub != 0) 142 printf("+(\\n[" WIDTH_FORMAT "]-\\n[" SUB_KERN_FORMAT "]+%dM)>?0\n", 143 sub->uid, p->uid, script_space); 144 else if (sup != 0) 145 printf("+(\\n[" WIDTH_FORMAT "]+%dM)>?0\n", sup->uid, script_space); 146 else 147 printf("\n"); 148 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]", 149 uid, p->uid); 150 if (sup != 0) 151 printf(">?(\\n[" SUP_RAISE_FORMAT "]+\\n[" HEIGHT_FORMAT "])", 152 uid, sup->uid); 153 if (sub != 0) 154 printf(">?(-\\n[" SUB_LOWER_FORMAT "]+\\n[" HEIGHT_FORMAT "])", 155 uid, sub->uid); 156 printf("\n"); 157 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]", 158 uid, p->uid); 159 if (sub != 0) 160 printf(">?(\\n[" SUB_LOWER_FORMAT "]+\\n[" DEPTH_FORMAT "])", 161 uid, sub->uid); 162 if (sup != 0) 163 printf(">?(-\\n[" SUP_RAISE_FORMAT "]+\\n[" DEPTH_FORMAT "])", 164 uid, sup->uid); 165 printf("\n"); 166 return res; 167} 168 169void script_box::output() 170{ 171 p->output(); 172 if (sup != 0) { 173 printf("\\Z" DELIMITER_CHAR); 174 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 175 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 176 sup->output(); 177 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 178 printf(DELIMITER_CHAR); 179 } 180 if (sub != 0) { 181 printf("\\Z" DELIMITER_CHAR); 182 printf("\\v'\\n[" SUB_LOWER_FORMAT "]u'", uid); 183 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 184 printf("\\h'-\\n[" SUB_KERN_FORMAT "]u'", p->uid); 185 sub->output(); 186 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 187 printf(DELIMITER_CHAR); 188 } 189 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u'", 190 uid, p->uid); 191} 192 193void script_box::hint(unsigned flags) 194{ 195 p->hint(flags & ~HINT_NEXT_IS_ITALIC); 196} 197 198void script_box::debug_print() 199{ 200 fprintf(stderr, "{ "); 201 p->debug_print(); 202 fprintf(stderr, " }"); 203 if (sub) { 204 fprintf(stderr, " sub { "); 205 sub->debug_print(); 206 fprintf(stderr, " }"); 207 } 208 if (sup) { 209 fprintf(stderr, " sup { "); 210 sup->debug_print(); 211 fprintf(stderr, " }"); 212 } 213} 214 215void script_box::check_tabs(int level) 216{ 217 if (sup) 218 sup->check_tabs(level + 1); 219 if (sub) 220 sub->check_tabs(level + 1); 221 p->check_tabs(level); 222} 223