1// -*- C++ -*- 2/* Copyright (C) 1989, 1990, 1991, 1992, 2002 Free Software Foundation, Inc. 3 Written by James Clark (jjc@jclark.com) 4 5This file is part of groff. 6 7groff is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12groff is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License along 18with groff; see the file COPYING. If not, write to the Free Software 19Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 20 21#include "eqn.h" 22#include "pbox.h" 23 24class accent_box : public pointer_box { 25private: 26 box *ab; 27public: 28 accent_box(box *, box *); 29 ~accent_box(); 30 int compute_metrics(int); 31 void output(); 32 void debug_print(); 33 void check_tabs(int); 34}; 35 36box *make_accent_box(box *p, box *q) 37{ 38 return new accent_box(p, q); 39} 40 41accent_box::accent_box(box *pp, box *qq) : pointer_box(pp), ab(qq) 42{ 43} 44 45accent_box::~accent_box() 46{ 47 delete ab; 48} 49 50#if 0 51int accent_box::compute_metrics(int style) 52{ 53 int r = p->compute_metrics(style); 54 p->compute_skew(); 55 ab->compute_metrics(style); 56 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 57 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 58 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", 59 uid, p->uid, x_height); 60 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n[" 61 SUP_RAISE_FORMAT "]\n", 62 uid, ab->uid, uid); 63 return r; 64} 65 66void accent_box::output() 67{ 68 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" 69 SKEW_FORMAT "]u'", 70 p->uid, ab->uid, p->uid); 71 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 72 ab->output(); 73 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid); 74 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 75 printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n[" 76 SKEW_FORMAT "]u)'", 77 p->uid, ab->uid, p->uid); 78 p->output(); 79} 80#endif 81 82/* This version copes with the possibility of an accent's being wider 83than its accentee. LEFT_WIDTH_FORMAT gives the distance from the 84left edge of the resulting box to the middle of the accentee's box.*/ 85 86int accent_box::compute_metrics(int style) 87{ 88 int r = p->compute_metrics(style); 89 p->compute_skew(); 90 ab->compute_metrics(style); 91 printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" 92 ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n", 93 uid, p->uid, ab->uid, p->uid); 94 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" 95 ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])" 96 "+\\n[" LEFT_WIDTH_FORMAT "]\n", 97 uid, p->uid, ab->uid, p->uid, uid); 98 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 99 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n", 100 uid, p->uid, x_height); 101 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n[" 102 SUP_RAISE_FORMAT "]\n", 103 uid, ab->uid, uid); 104 if (r) 105 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]" 106 "-(\\n[" WIDTH_FORMAT "]/2)'\n", 107 uid, p->uid); 108 return r; 109} 110 111void accent_box::output() 112{ 113 printf("\\Z" DELIMITER_CHAR); 114 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u" 115 "-(\\n[" WIDTH_FORMAT "]u/2u)'", 116 uid, p->uid, ab->uid); 117 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 118 ab->output(); 119 printf(DELIMITER_CHAR); 120 printf("\\Z" DELIMITER_CHAR); 121 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", 122 uid, p->uid); 123 p->output(); 124 printf(DELIMITER_CHAR); 125 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); 126} 127 128void accent_box::check_tabs(int level) 129{ 130 ab->check_tabs(level + 1); 131 p->check_tabs(level + 1); 132} 133 134void accent_box::debug_print() 135{ 136 fprintf(stderr, "{ "); 137 p->debug_print(); 138 fprintf(stderr, " } accent { "); 139 ab->debug_print(); 140 fprintf(stderr, " }"); 141} 142 143class overline_char_box : public simple_box { 144public: 145 overline_char_box(); 146 void output(); 147 void debug_print(); 148}; 149 150overline_char_box::overline_char_box() 151{ 152} 153 154void overline_char_box::output() 155{ 156 printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height); 157 printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), 158 accent_width); 159 printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height); 160} 161 162void overline_char_box::debug_print() 163{ 164 fprintf(stderr, "<overline char>"); 165} 166 167class overline_box : public pointer_box { 168public: 169 overline_box(box *); 170 int compute_metrics(int); 171 void output(); 172 void debug_print(); 173}; 174 175box *make_overline_box(box *p) 176{ 177 if (p->is_char()) 178 return new accent_box(p, new overline_char_box); 179 else 180 return new overline_box(p); 181} 182 183overline_box::overline_box(box *pp) : pointer_box(pp) 184{ 185} 186 187int overline_box::compute_metrics(int style) 188{ 189 int r = p->compute_metrics(cramped_style(style)); 190 // 9 191 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n", 192 uid, p->uid, default_rule_thickness*5); 193 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 194 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 195 return r; 196} 197 198void overline_box::output() 199{ 200 // 9 201 printf("\\Z" DELIMITER_CHAR); 202 printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'", 203 p->uid, 7*default_rule_thickness); 204 if (draw_flag) 205 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); 206 else 207 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); 208 printf(DELIMITER_CHAR); 209 p->output(); 210} 211 212void overline_box::debug_print() 213{ 214 fprintf(stderr, "{ "); 215 p->debug_print(); 216 fprintf(stderr, " } bar"); 217} 218 219class uaccent_box : public pointer_box { 220 box *ab; 221public: 222 uaccent_box(box *, box *); 223 ~uaccent_box(); 224 int compute_metrics(int); 225 void output(); 226 void compute_subscript_kern(); 227 void check_tabs(int); 228 void debug_print(); 229}; 230 231box *make_uaccent_box(box *p, box *q) 232{ 233 return new uaccent_box(p, q); 234} 235 236uaccent_box::uaccent_box(box *pp, box *qq) 237: pointer_box(pp), ab(qq) 238{ 239} 240 241uaccent_box::~uaccent_box() 242{ 243 delete ab; 244} 245 246int uaccent_box::compute_metrics(int style) 247{ 248 int r = p->compute_metrics(style); 249 ab->compute_metrics(style); 250 printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" 251 ">?(\\n[" WIDTH_FORMAT "]/2)\n", 252 uid, p->uid, ab->uid); 253 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2" 254 ">?(\\n[" WIDTH_FORMAT "]/2)" 255 "+\\n[" LEFT_WIDTH_FORMAT "]\n", 256 uid, p->uid, ab->uid, uid); 257 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 258 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]" 259 "+\\n[" DEPTH_FORMAT "]\n", 260 uid, p->uid, ab->uid); 261 if (r) 262 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]" 263 "-(\\n[" WIDTH_FORMAT "]/2)'\n", 264 uid, p->uid); 265 return r; 266} 267 268void uaccent_box::output() 269{ 270 printf("\\Z" DELIMITER_CHAR); 271 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", 272 uid, ab->uid); 273 printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid); 274 ab->output(); 275 printf(DELIMITER_CHAR); 276 printf("\\Z" DELIMITER_CHAR); 277 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'", 278 uid, p->uid); 279 p->output(); 280 printf(DELIMITER_CHAR); 281 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid); 282} 283 284void uaccent_box::check_tabs(int level) 285{ 286 ab->check_tabs(level + 1); 287 p->check_tabs(level + 1); 288} 289 290void uaccent_box::compute_subscript_kern() 291{ 292 box::compute_subscript_kern(); // want 0 subscript kern 293} 294 295void uaccent_box::debug_print() 296{ 297 fprintf(stderr, "{ "); 298 p->debug_print(); 299 fprintf(stderr, " } uaccent { "); 300 ab->debug_print(); 301 fprintf(stderr, " }"); 302} 303 304class underline_char_box : public simple_box { 305public: 306 underline_char_box(); 307 void output(); 308 void debug_print(); 309}; 310 311underline_char_box::underline_char_box() 312{ 313} 314 315void underline_char_box::output() 316{ 317 printf("\\v'%dM/2u'", 7*default_rule_thickness); 318 printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"), 319 accent_width); 320 printf("\\v'-%dM/2u'", 7*default_rule_thickness); 321} 322 323void underline_char_box::debug_print() 324{ 325 fprintf(stderr, "<underline char>"); 326} 327 328 329class underline_box : public pointer_box { 330public: 331 underline_box(box *); 332 int compute_metrics(int); 333 void output(); 334 void compute_subscript_kern(); 335 void debug_print(); 336}; 337 338box *make_underline_box(box *p) 339{ 340 if (p->is_char()) 341 return new uaccent_box(p, new underline_char_box); 342 else 343 return new underline_box(p); 344} 345 346underline_box::underline_box(box *pp) : pointer_box(pp) 347{ 348} 349 350int underline_box::compute_metrics(int style) 351{ 352 int r = p->compute_metrics(style); 353 // 10 354 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n", 355 uid, p->uid, default_rule_thickness*5); 356 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 357 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 358 return r; 359} 360 361void underline_box::output() 362{ 363 // 10 364 printf("\\Z" DELIMITER_CHAR); 365 printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'", 366 p->uid, 7*default_rule_thickness); 367 if (draw_flag) 368 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid); 369 else 370 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid); 371 printf(DELIMITER_CHAR); 372 p->output(); 373} 374 375// we want an underline box to have 0 subscript kern 376 377void underline_box::compute_subscript_kern() 378{ 379 box::compute_subscript_kern(); 380} 381 382void underline_box::debug_print() 383{ 384 fprintf(stderr, "{ "); 385 p->debug_print(); 386 fprintf(stderr, " } under"); 387} 388 389size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s) 390{ 391} 392 393int size_box::compute_metrics(int style) 394{ 395 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid); 396 printf(".ps %s\n", size); 397 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid); 398 int r = p->compute_metrics(style); 399 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid); 400 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 401 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 402 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 403 return r; 404} 405 406void size_box::output() 407{ 408 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid); 409 p->output(); 410 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid); 411} 412 413size_box::~size_box() 414{ 415 a_delete size; 416} 417 418void size_box::debug_print() 419{ 420 fprintf(stderr, "size %s { ", size); 421 p->debug_print(); 422 fprintf(stderr, " }"); 423} 424 425 426font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s) 427{ 428} 429 430font_box::~font_box() 431{ 432 a_delete f; 433} 434 435int font_box::compute_metrics(int style) 436{ 437 const char *old_roman_font = current_roman_font; 438 current_roman_font = f; 439 printf(".nr " FONT_FORMAT " \\n[.f]\n", uid); 440 printf(".ft %s\n", f); 441 int r = p->compute_metrics(style); 442 current_roman_font = old_roman_font; 443 printf(".ft \\n[" FONT_FORMAT "]\n", uid); 444 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 445 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 446 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 447 return r; 448} 449 450void font_box::output() 451{ 452 printf("\\f[%s]", f); 453 const char *old_roman_font = current_roman_font; 454 current_roman_font = f; 455 p->output(); 456 current_roman_font = old_roman_font; 457 printf("\\f[\\n[" FONT_FORMAT "]]", uid); 458} 459 460void font_box::debug_print() 461{ 462 fprintf(stderr, "font %s { ", f); 463 p->debug_print(); 464 fprintf(stderr, " }"); 465} 466 467fat_box::fat_box(box *pp) : pointer_box(pp) 468{ 469} 470 471int fat_box::compute_metrics(int style) 472{ 473 int r = p->compute_metrics(style); 474 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n", 475 uid, p->uid, fat_offset); 476 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 477 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 478 return r; 479} 480 481void fat_box::output() 482{ 483 p->output(); 484 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid); 485 printf("\\h'%dM'", fat_offset); 486 p->output(); 487} 488 489 490void fat_box::debug_print() 491{ 492 fprintf(stderr, "fat { "); 493 p->debug_print(); 494 fprintf(stderr, " }"); 495} 496 497 498vmotion_box::vmotion_box(int i, box *pp) : pointer_box(pp), n(i) 499{ 500} 501 502int vmotion_box::compute_metrics(int style) 503{ 504 int r = p->compute_metrics(style); 505 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 506 if (n > 0) { 507 printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n", 508 uid, n, p->uid); 509 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 510 } 511 else { 512 printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n", 513 uid, -n, p->uid); 514 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", 515 uid, p->uid); 516 } 517 return r; 518} 519 520void vmotion_box::output() 521{ 522 printf("\\v'%dM'", -n); 523 p->output(); 524 printf("\\v'%dM'", n); 525} 526 527void vmotion_box::debug_print() 528{ 529 if (n >= 0) 530 fprintf(stderr, "up %d { ", n); 531 else 532 fprintf(stderr, "down %d { ", -n); 533 p->debug_print(); 534 fprintf(stderr, " }"); 535} 536 537hmotion_box::hmotion_box(int i, box *pp) : pointer_box(pp), n(i) 538{ 539} 540 541int hmotion_box::compute_metrics(int style) 542{ 543 int r = p->compute_metrics(style); 544 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n", 545 uid, p->uid, n); 546 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid); 547 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid); 548 if (r) 549 printf(".nr " MARK_REG " +%dM\n", n); 550 return r; 551} 552 553void hmotion_box::output() 554{ 555 printf("\\h'%dM'", n); 556 p->output(); 557} 558 559void hmotion_box::debug_print() 560{ 561 if (n >= 0) 562 fprintf(stderr, "fwd %d { ", n); 563 else 564 fprintf(stderr, "back %d { ", -n); 565 p->debug_print(); 566 fprintf(stderr, " }"); 567} 568 569vcenter_box::vcenter_box(box *pp) : pointer_box(pp) 570{ 571} 572 573int vcenter_box::compute_metrics(int style) 574{ 575 int r = p->compute_metrics(style); 576 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid); 577 printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n[" 578 HEIGHT_FORMAT "]/2+%dM\n", 579 uid, p->uid, p->uid, axis_height); 580 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n[" 581 SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid); 582 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n[" 583 SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid); 584 585 return r; 586} 587 588void vcenter_box::output() 589{ 590 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid); 591 p->output(); 592 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid); 593} 594 595void vcenter_box::debug_print() 596{ 597 fprintf(stderr, "vcenter { "); 598 p->debug_print(); 599 fprintf(stderr, " }"); 600} 601 602