2 /* Copyright (C) 1989-2014 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 class accent_box : public pointer_box {
27 accent_box(box *, box *);
29 int compute_metrics(int);
35 box *make_accent_box(box *p, box *q)
37 return new accent_box(p, q);
40 accent_box::accent_box(box *pp, box *qq) : pointer_box(pp), ab(qq)
44 accent_box::~accent_box()
50 int accent_box::compute_metrics(int style)
52 int r = p->compute_metrics(style);
54 ab->compute_metrics(style);
55 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
56 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
57 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
58 uid, p->uid, x_height);
59 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
60 SUP_RAISE_FORMAT "]\n",
65 void accent_box::output()
67 if (output_format == troff) {
68 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
70 p->uid, ab->uid, p->uid);
71 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
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["
77 p->uid, ab->uid, p->uid);
80 else if (output_format == mathml) {
81 printf("<mover accent='true'>");
89 /* This version copes with the possibility of an accent's being wider
90 than its accentee. LEFT_WIDTH_FORMAT gives the distance from the
91 left edge of the resulting box to the middle of the accentee's box.*/
93 int accent_box::compute_metrics(int style)
95 int r = p->compute_metrics(style);
97 ab->compute_metrics(style);
98 printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
99 ">?(\\n[" WIDTH_FORMAT "]/2-\\n[" SKEW_FORMAT "])\n",
100 uid, p->uid, ab->uid, p->uid);
101 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
102 ">?(\\n[" WIDTH_FORMAT "]/2+\\n[" SKEW_FORMAT "])"
103 "+\\n[" LEFT_WIDTH_FORMAT "]\n",
104 uid, p->uid, ab->uid, p->uid, uid);
105 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
106 printf(".nr " SUP_RAISE_FORMAT " \\n[" HEIGHT_FORMAT "]-%dM>?0\n",
107 uid, p->uid, x_height);
108 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
109 SUP_RAISE_FORMAT "]\n",
112 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
113 "-(\\n[" WIDTH_FORMAT "]/2)'\n",
118 void accent_box::output()
120 if (output_format == troff) {
121 printf("\\Z" DELIMITER_CHAR);
122 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u+\\n[" SKEW_FORMAT "]u"
123 "-(\\n[" WIDTH_FORMAT "]u/2u)'",
124 uid, p->uid, ab->uid);
125 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
127 printf(DELIMITER_CHAR);
128 printf("\\Z" DELIMITER_CHAR);
129 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
132 printf(DELIMITER_CHAR);
133 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
135 else if (output_format == mathml) {
136 printf("<mover accent='true'>");
143 void accent_box::check_tabs(int level)
145 ab->check_tabs(level + 1);
146 p->check_tabs(level + 1);
149 void accent_box::debug_print()
151 fprintf(stderr, "{ ");
153 fprintf(stderr, " } accent { ");
155 fprintf(stderr, " }");
158 class overline_char_box : public simple_box {
165 overline_char_box::overline_char_box()
169 void overline_char_box::output()
171 if (output_format == troff) {
172 printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness, x_height);
173 printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
175 printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
177 else if (output_format == mathml)
178 printf("<mo>¯</mo>");
181 void overline_char_box::debug_print()
183 fprintf(stderr, "<overline char>");
186 class overline_box : public pointer_box {
189 int compute_metrics(int);
194 box *make_overline_box(box *p)
197 return new accent_box(p, new overline_char_box);
199 return new overline_box(p);
202 overline_box::overline_box(box *pp) : pointer_box(pp)
206 int overline_box::compute_metrics(int style)
208 int r = p->compute_metrics(cramped_style(style));
210 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+%dM\n",
211 uid, p->uid, default_rule_thickness*5);
212 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
213 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
217 void overline_box::output()
219 if (output_format == troff) {
221 printf("\\Z" DELIMITER_CHAR);
222 printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
223 p->uid, 7*default_rule_thickness);
225 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
227 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
228 printf(DELIMITER_CHAR);
231 else if (output_format == mathml) {
232 printf("<mover accent='false'>");
234 printf("<mo>¯</mo></mover>");
238 void overline_box::debug_print()
240 fprintf(stderr, "{ ");
242 fprintf(stderr, " } bar");
245 class uaccent_box : public pointer_box {
248 uaccent_box(box *, box *);
250 int compute_metrics(int);
252 void compute_subscript_kern();
253 void check_tabs(int);
257 box *make_uaccent_box(box *p, box *q)
259 return new uaccent_box(p, q);
262 uaccent_box::uaccent_box(box *pp, box *qq)
263 : pointer_box(pp), ab(qq)
267 uaccent_box::~uaccent_box()
272 int uaccent_box::compute_metrics(int style)
274 int r = p->compute_metrics(style);
275 ab->compute_metrics(style);
276 printf(".nr " LEFT_WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
277 ">?(\\n[" WIDTH_FORMAT "]/2)\n",
278 uid, p->uid, ab->uid);
279 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]/2"
280 ">?(\\n[" WIDTH_FORMAT "]/2)"
281 "+\\n[" LEFT_WIDTH_FORMAT "]\n",
282 uid, p->uid, ab->uid, uid);
283 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
284 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]"
285 "+\\n[" DEPTH_FORMAT "]\n",
286 uid, p->uid, ab->uid);
288 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
289 "-(\\n[" WIDTH_FORMAT "]/2)'\n",
294 void uaccent_box::output()
296 if (output_format == troff) {
297 printf("\\Z" DELIMITER_CHAR);
298 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
300 printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid);
302 printf(DELIMITER_CHAR);
303 printf("\\Z" DELIMITER_CHAR);
304 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
307 printf(DELIMITER_CHAR);
308 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
310 else if (output_format == mathml) {
311 printf("<munder accent='true'>");
318 void uaccent_box::check_tabs(int level)
320 ab->check_tabs(level + 1);
321 p->check_tabs(level + 1);
324 void uaccent_box::compute_subscript_kern()
326 box::compute_subscript_kern(); // want 0 subscript kern
329 void uaccent_box::debug_print()
331 fprintf(stderr, "{ ");
333 fprintf(stderr, " } uaccent { ");
335 fprintf(stderr, " }");
338 class underline_char_box : public simple_box {
340 underline_char_box();
345 underline_char_box::underline_char_box()
349 void underline_char_box::output()
351 if (output_format == troff) {
352 printf("\\v'%dM/2u'", 7*default_rule_thickness);
353 printf((draw_flag ? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
355 printf("\\v'-%dM/2u'", 7*default_rule_thickness);
357 else if (output_format == mathml)
358 printf("<mo>_</mo>");
361 void underline_char_box::debug_print()
363 fprintf(stderr, "<underline char>");
367 class underline_box : public pointer_box {
369 underline_box(box *);
370 int compute_metrics(int);
372 void compute_subscript_kern();
376 box *make_underline_box(box *p)
379 return new uaccent_box(p, new underline_char_box);
381 return new underline_box(p);
384 underline_box::underline_box(box *pp) : pointer_box(pp)
388 int underline_box::compute_metrics(int style)
390 int r = p->compute_metrics(style);
392 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]+%dM\n",
393 uid, p->uid, default_rule_thickness*5);
394 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
395 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
399 void underline_box::output()
401 if (output_format == troff) {
403 printf("\\Z" DELIMITER_CHAR);
404 printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
405 p->uid, 7*default_rule_thickness);
407 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
409 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
410 printf(DELIMITER_CHAR);
413 else if (output_format == mathml) {
414 printf("<munder accent='true'>");
416 printf("<mo>¯</mo></munder>");
420 // we want an underline box to have 0 subscript kern
422 void underline_box::compute_subscript_kern()
424 box::compute_subscript_kern();
427 void underline_box::debug_print()
429 fprintf(stderr, "{ ");
431 fprintf(stderr, " } under");
434 size_box::size_box(char *s, box *pp) : pointer_box(pp), size(s)
438 int size_box::compute_metrics(int style)
440 printf(".nr " SIZE_FORMAT " \\n[.ps]\n", uid);
441 printf(".ps %s\n", size);
442 printf(".nr " SMALL_SIZE_FORMAT " \\n[.ps]\n", uid);
443 int r = p->compute_metrics(style);
444 printf(".ps \\n[" SIZE_FORMAT "]u\n", uid);
445 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
446 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
447 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
451 void size_box::output()
453 if (output_format == troff) {
454 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
456 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
458 else if (output_format == mathml) {
459 printf("<mstyle mathsize='%s'>", size);
465 size_box::~size_box()
470 void size_box::debug_print()
472 fprintf(stderr, "size %s { ", size);
474 fprintf(stderr, " }");
478 font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s)
482 font_box::~font_box()
487 int font_box::compute_metrics(int style)
489 const char *old_roman_font = current_roman_font;
490 current_roman_font = f;
491 printf(".nr " FONT_FORMAT " \\n[.f]\n", uid);
492 printf(".ft %s\n", f);
493 int r = p->compute_metrics(style);
494 current_roman_font = old_roman_font;
495 printf(".ft \\n[" FONT_FORMAT "]\n", uid);
496 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
497 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
498 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
502 void font_box::output()
504 if (output_format == troff) {
505 printf("\\f[%s]", f);
506 const char *old_roman_font = current_roman_font;
507 current_roman_font = f;
509 current_roman_font = old_roman_font;
510 printf("\\f[\\n[" FONT_FORMAT "]]", uid);
512 else if (output_format == mathml) {
513 const char *mlfont = f;
514 // bold and italic are already in MathML; translate eqn roman here
530 printf("<mstyle mathvariant='%s'>", mlfont);
536 void font_box::debug_print()
538 fprintf(stderr, "font %s { ", f);
540 fprintf(stderr, " }");
543 fat_box::fat_box(box *pp) : pointer_box(pp)
547 int fat_box::compute_metrics(int style)
549 int r = p->compute_metrics(style);
550 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
551 uid, p->uid, fat_offset);
552 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
553 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
557 void fat_box::output()
559 if (output_format == troff) {
561 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
562 printf("\\h'%dM'", fat_offset);
565 else if (output_format == mathml) {
566 printf("<mstyle mathvariant='double-struck'>");
573 void fat_box::debug_print()
575 fprintf(stderr, "fat { ");
577 fprintf(stderr, " }");
581 vmotion_box::vmotion_box(int i, box *pp) : pointer_box(pp), n(i)
585 int vmotion_box::compute_metrics(int style)
587 int r = p->compute_metrics(style);
588 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
590 printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n",
592 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
595 printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n",
597 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n",
603 void vmotion_box::output()
605 if (output_format == troff) {
606 printf("\\v'%dM'", -n);
608 printf("\\v'%dM'", n);
610 else if (output_format == mathml) {
611 printf("<merror>eqn vertical motion cannot be expressed "
612 "in MathML</merror>");
617 void vmotion_box::debug_print()
620 fprintf(stderr, "up %d { ", n);
622 fprintf(stderr, "down %d { ", -n);
624 fprintf(stderr, " }");
627 hmotion_box::hmotion_box(int i, box *pp) : pointer_box(pp), n(i)
631 int hmotion_box::compute_metrics(int style)
633 int r = p->compute_metrics(style);
634 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]+%dM\n",
636 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n", uid, p->uid);
637 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
639 printf(".nr " MARK_REG " +%dM\n", n);
643 void hmotion_box::output()
645 if (output_format == troff) {
646 printf("\\h'%dM'", n);
649 else if (output_format == mathml) {
650 printf("<merror>eqn horizontal motion cannot be expessed "
651 "in MathML</merror>");
656 void hmotion_box::debug_print()
659 fprintf(stderr, "fwd %d { ", n);
661 fprintf(stderr, "back %d { ", -n);
663 fprintf(stderr, " }");
666 vcenter_box::vcenter_box(box *pp) : pointer_box(pp)
670 int vcenter_box::compute_metrics(int style)
672 int r = p->compute_metrics(style);
673 printf(".nr " WIDTH_FORMAT " 0\\n[" WIDTH_FORMAT "]\n", uid, p->uid);
674 printf(".nr " SUP_RAISE_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
675 HEIGHT_FORMAT "]/2+%dM\n",
676 uid, p->uid, p->uid, axis_height);
677 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]+\\n["
678 SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
679 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]-\\n["
680 SUP_RAISE_FORMAT "]>?0\n", uid, p->uid, uid);
685 void vcenter_box::output()
687 if (output_format == troff)
688 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
690 if (output_format == troff)
691 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
694 void vcenter_box::debug_print()
696 fprintf(stderr, "vcenter { ");
698 fprintf(stderr, " }");