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