2 /* Copyright (C) 1989, 1990, 1991, 1992, 2002, 2007, 2009
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 class accent_box : public pointer_box {
28 accent_box(box *, box *);
30 int compute_metrics(int);
36 box *make_accent_box(box *p, box *q)
38 return new accent_box(p, q);
41 accent_box::accent_box(box *pp, box *qq) : pointer_box(pp), ab(qq)
45 accent_box::~accent_box()
51 int accent_box::compute_metrics(int style)
53 int r = p->compute_metrics(style);
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",
66 void accent_box::output()
68 if (output_format == troff) {
69 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
71 p->uid, ab->uid, p->uid);
72 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
74 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", ab->uid);
75 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
76 printf("\\h'-(\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
78 p->uid, ab->uid, p->uid);
81 else if (output_format == mathml) {
82 printf("<mover accent='true'>");
90 /* This version copes with the possibility of an accent's being wider
91 than its accentee. LEFT_WIDTH_FORMAT gives the distance from the
92 left edge of the resulting box to the middle of the accentee's box.*/
94 int accent_box::compute_metrics(int style)
96 int r = p->compute_metrics(style);
98 ab->compute_metrics(style);
99 printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
100 ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n",
101 uid, p->uid, ab->uid, p->uid);
102 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
103 ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])"
104 "+\\n[" LEFT_WIDTH_FORMAT "]\n",
105 uid, p->uid, ab->uid, p->uid, uid);
106 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
107 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
108 uid, p->uid, x_height);
109 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
110 SUP_RAISE_FORMAT "]\n",
113 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
114 "-(\\n[" WIDTH_FORMAT "]/2)'\n",
119 void accent_box::output()
121 if (output_format == troff) {
122 printf("\\Z" DELIMITER_CHAR);
123 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u"
124 "-(\\n[" WIDTH_FORMAT "]u/2u)'",
125 uid, p->uid, ab->uid);
126 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
128 printf(DELIMITER_CHAR);
129 printf("\\Z" DELIMITER_CHAR);
130 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
133 printf(DELIMITER_CHAR);
134 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
136 else if (output_format == mathml) {
137 printf("<mover accent='true'>");
144 void accent_box::check_tabs(int level)
146 ab->check_tabs(level + 1);
147 p->check_tabs(level + 1);
150 void accent_box::debug_print()
152 fprintf(stderr, "{ ");
154 fprintf(stderr, " } accent { ");
156 fprintf(stderr, " }");
159 class overline_char_box : public simple_box {
166 overline_char_box::overline_char_box()
170 void overline_char_box::output()
172 if (output_format == troff) {
173 printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height);
174 printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
176 printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
178 else if (output_format == mathml)
179 printf("<mo>¯</mo>");
182 void overline_char_box::debug_print()
184 fprintf(stderr, "<overline char>");
187 class overline_box : public pointer_box {
190 int compute_metrics(int);
195 box *make_overline_box(box *p)
198 return new accent_box(p, new overline_char_box);
200 return new overline_box(p);
203 overline_box::overline_box(box *pp) : pointer_box(pp)
207 int overline_box::compute_metrics(int style)
209 int r = p->compute_metrics(cramped_style(style));
211 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n",
212 uid, p->uid, default_rule_thickness*5);
213 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
214 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
218 void overline_box::output()
220 if (output_format == troff) {
222 printf("\\Z" DELIMITER_CHAR);
223 printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
224 p->uid, 7*default_rule_thickness);
226 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
228 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
229 printf(DELIMITER_CHAR);
232 else if (output_format == mathml) {
233 printf("<mover accent='false'>");
235 printf("<mo>¯</mo></mover>");
239 void overline_box::debug_print()
241 fprintf(stderr, "{ ");
243 fprintf(stderr, " } bar");
246 class uaccent_box : public pointer_box {
249 uaccent_box(box *, box *);
251 int compute_metrics(int);
253 void compute_subscript_kern();
254 void check_tabs(int);
258 box *make_uaccent_box(box *p, box *q)
260 return new uaccent_box(p, q);
263 uaccent_box::uaccent_box(box *pp, box *qq)
264 : pointer_box(pp), ab(qq)
268 uaccent_box::~uaccent_box()
273 int uaccent_box::compute_metrics(int style)
275 int r = p->compute_metrics(style);
276 ab->compute_metrics(style);
277 printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
278 ">?(\\n[" WIDTH_FORMAT "]/2)\n",
279 uid, p->uid, ab->uid);
280 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
281 ">?(\\n[" WIDTH_FORMAT "]/2)"
282 "+\\n[" LEFT_WIDTH_FORMAT "]\n",
283 uid, p->uid, ab->uid, uid);
284 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
285 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
286 "+\\n[" DEPTH_FORMAT "]\n",
287 uid, p->uid, ab->uid);
289 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
290 "-(\\n[" WIDTH_FORMAT "]/2)'\n",
295 void uaccent_box::output()
297 if (output_format == troff) {
298 printf("\\Z" DELIMITER_CHAR);
299 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
301 printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid);
303 printf(DELIMITER_CHAR);
304 printf("\\Z" DELIMITER_CHAR);
305 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
308 printf(DELIMITER_CHAR);
309 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
311 else if (output_format == mathml) {
312 printf("<munder accent='true'>");
319 void uaccent_box::check_tabs(int level)
321 ab->check_tabs(level + 1);
322 p->check_tabs(level + 1);
325 void uaccent_box::compute_subscript_kern()
327 box::compute_subscript_kern(); // want 0 subscript kern
330 void uaccent_box::debug_print()
332 fprintf(stderr, "{ ");
334 fprintf(stderr, " } uaccent { ");
336 fprintf(stderr, " }");
339 class underline_char_box : public simple_box {
341 underline_char_box();
346 underline_char_box::underline_char_box()
350 void underline_char_box::output()
352 if (output_format == troff) {
353 printf("\\v'%dM/2u'", 7*default_rule_thickness);
354 printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
356 printf("\\v'-%dM/2u'", 7*default_rule_thickness);
358 else if (output_format == mathml)
359 printf("<mo>_</mo>");
362 void underline_char_box::debug_print()
364 fprintf(stderr, "<underline char>");
368 class underline_box : public pointer_box {
370 underline_box(box *);
371 int compute_metrics(int);
373 void compute_subscript_kern();
377 box *make_underline_box(box *p)
380 return new uaccent_box(p, new underline_char_box);
382 return new underline_box(p);
385 underline_box::underline_box(box *pp) : pointer_box(pp)
389 int underline_box::compute_metrics(int style)
391 int r = p->compute_metrics(style);
393 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
394 uid, p->uid, default_rule_thickness*5);
395 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
396 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
400 void underline_box::output()
402 if (output_format == troff) {
404 printf("\\Z" DELIMITER_CHAR);
405 printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
406 p->uid, 7*default_rule_thickness);
408 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
410 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
411 printf(DELIMITER_CHAR);
414 else if (output_format == mathml) {
415 printf("<munder accent='true'>");
417 printf("<mo>¯</mo></munder>");
421 // we want an underline box to have 0 subscript kern
423 void underline_box::compute_subscript_kern()
425 box::compute_subscript_kern();
428 void underline_box::debug_print()
430 fprintf(stderr, "{ ");
432 fprintf(stderr, " } under");
435 size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s)
439 int size_box::compute_metrics(int style)
441 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
442 printf(".ps %s\n", size);
443 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
444 int r = p->compute_metrics(style);
445 printf(".ps \\n[" SIZE_FORMAT "]u\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);
452 void size_box::output()
454 if (output_format == troff) {
455 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
457 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
459 else if (output_format == mathml) {
460 printf("<mstyle mathsize='%s'>", size);
466 size_box::~size_box()
471 void size_box::debug_print()
473 fprintf(stderr, "size %s { ", size);
475 fprintf(stderr, " }");
479 font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s)
483 font_box::~font_box()
488 int font_box::compute_metrics(int style)
490 const char *old_roman_font = current_roman_font;
491 current_roman_font = f;
492 printf(".nr " FONT_FORMAT " \\n[.f]\n", uid);
493 printf(".ft %s\n", f);
494 int r = p->compute_metrics(style);
495 current_roman_font = old_roman_font;
496 printf(".ft \\n[" FONT_FORMAT "]\n", uid);
497 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
498 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
499 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
503 void font_box::output()
505 if (output_format == troff) {
506 printf("\\f[%s]", f);
507 const char *old_roman_font = current_roman_font;
508 current_roman_font = f;
510 current_roman_font = old_roman_font;
511 printf("\\f[\\n[" FONT_FORMAT "]]", uid);
513 else if (output_format == mathml) {
514 const char *mlfont = f;
515 // bold and italic are already in MathML; translate eqn roman here
531 printf("<mstyle mathvariant='%s'>", mlfont);
537 void font_box::debug_print()
539 fprintf(stderr, "font %s { ", f);
541 fprintf(stderr, " }");
544 fat_box::fat_box(box *pp) : pointer_box(pp)
548 int fat_box::compute_metrics(int style)
550 int r = p->compute_metrics(style);
551 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
552 uid, p->uid, fat_offset);
553 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
554 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
558 void fat_box::output()
560 if (output_format == troff) {
562 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
563 printf("\\h'%dM'", fat_offset);
566 else if (output_format == mathml) {
567 printf("<mstyle mathvariant='double-struck'>");
574 void fat_box::debug_print()
576 fprintf(stderr, "fat { ");
578 fprintf(stderr, " }");
582 vmotion_box::vmotion_box(int i, box *pp) : pointer_box(pp), n(i)
586 int vmotion_box::compute_metrics(int style)
588 int r = p->compute_metrics(style);
589 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
591 printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n",
593 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
596 printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n",
598 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n",
604 void vmotion_box::output()
606 if (output_format == troff) {
607 printf("\\v'%dM'", -n);
609 printf("\\v'%dM'", n);
611 else if (output_format == mathml) {
612 printf("<merror>eqn vertical motion cannot be expressed "
613 "in MathML</merror>");
618 void vmotion_box::debug_print()
621 fprintf(stderr, "up %d { ", n);
623 fprintf(stderr, "down %d { ", -n);
625 fprintf(stderr, " }");
628 hmotion_box::hmotion_box(int i, box *pp) : pointer_box(pp), n(i)
632 int hmotion_box::compute_metrics(int style)
634 int r = p->compute_metrics(style);
635 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
637 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
638 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
640 printf(".nr " MARK_REG " +%dM\n", n);
644 void hmotion_box::output()
646 if (output_format == troff) {
647 printf("\\h'%dM'", n);
650 else if (output_format == mathml) {
651 printf("<merror>eqn horizontal motion cannot be expessed "
652 "in MathML</merror>");
657 void hmotion_box::debug_print()
660 fprintf(stderr, "fwd %d { ", n);
662 fprintf(stderr, "back %d { ", -n);
664 fprintf(stderr, " }");
667 vcenter_box::vcenter_box(box *pp) : pointer_box(pp)
671 int vcenter_box::compute_metrics(int style)
673 int r = p->compute_metrics(style);
674 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
675 printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
676 HEIGHT_FORMAT "]/2+%dM\n",
677 uid, p->uid, p->uid, axis_height);
678 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
679 SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
680 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
681 SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
686 void vcenter_box::output()
688 if (output_format == troff)
689 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
691 if (output_format == troff)
692 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
695 void vcenter_box::debug_print()
697 fprintf(stderr, "vcenter { ");
699 fprintf(stderr, " }");