2 * Copyright (c) 2014 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989 - 1992, 2002, 2007
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
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 2, or (at your option) any later
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 along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
24 #include "eqn-config.h"
35 accent_box(box
*, box
*);
37 int compute_metrics(int);
43 box
*make_accent_box(box
*p
, box
*q
)
45 return new accent_box(p
, q
);
48 accent_box::accent_box(box
*pp
, box
*qq
) : pointer_box(pp
), ab(qq
)
52 accent_box::~accent_box()
58 int accent_box::compute_metrics(int style
)
60 int r
= p
->compute_metrics(style
);
62 ab
->compute_metrics(style
);
63 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
64 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
65 printf(".nr " SUP_RAISE_FORMAT
" \\n[" HEIGHT_FORMAT
"]-%dM>?0\n",
66 uid
, p
->uid
, x_height
);
67 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]+\\n["
68 SUP_RAISE_FORMAT
"]\n",
73 void accent_box::output()
75 if (output_format
== troff
) {
76 printf("\\h'\\n[" WIDTH_FORMAT
"]u-\\n[" WIDTH_FORMAT
"]u/2u+\\n["
78 p
->uid
, ab
->uid
, p
->uid
);
79 printf("\\v'-\\n[" SUP_RAISE_FORMAT
"]u'", uid
);
81 printf("\\h'-\\n[" WIDTH_FORMAT
"]u'", ab
->uid
);
82 printf("\\v'\\n[" SUP_RAISE_FORMAT
"]u'", uid
);
83 printf("\\h'-(\\n[" WIDTH_FORMAT
"]u-\\n[" WIDTH_FORMAT
"]u/2u+\\n["
85 p
->uid
, ab
->uid
, p
->uid
);
88 else if (output_format
== mathml
) {
89 printf("<mover accent='true'>");
97 /* This version copes with the possibility of an accent's being wider
98 than its accentee. LEFT_WIDTH_FORMAT gives the distance from the
99 left edge of the resulting box to the middle of the accentee's box.*/
101 int accent_box::compute_metrics(int style
)
103 int r
= p
->compute_metrics(style
);
105 ab
->compute_metrics(style
);
106 printf(".nr " LEFT_WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]/2"
107 ">?(\\n[" WIDTH_FORMAT
"]/2-\\n[" SKEW_FORMAT
"])\n",
108 uid
, p
->uid
, ab
->uid
, p
->uid
);
109 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]/2"
110 ">?(\\n[" WIDTH_FORMAT
"]/2+\\n[" SKEW_FORMAT
"])"
111 "+\\n[" LEFT_WIDTH_FORMAT
"]\n",
112 uid
, p
->uid
, ab
->uid
, p
->uid
, uid
);
113 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
114 printf(".nr " SUP_RAISE_FORMAT
" \\n[" HEIGHT_FORMAT
"]-%dM>?0\n",
115 uid
, p
->uid
, x_height
);
116 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]+\\n["
117 SUP_RAISE_FORMAT
"]\n",
120 printf(".nr " MARK_REG
" +\\n[" LEFT_WIDTH_FORMAT
"]"
121 "-(\\n[" WIDTH_FORMAT
"]/2)'\n",
126 void accent_box::output()
128 if (output_format
== troff
) {
129 printf("\\Z" DELIMITER_CHAR
);
130 printf("\\h'\\n[" LEFT_WIDTH_FORMAT
"]u+\\n[" SKEW_FORMAT
"]u"
131 "-(\\n[" WIDTH_FORMAT
"]u/2u)'",
132 uid
, p
->uid
, ab
->uid
);
133 printf("\\v'-\\n[" SUP_RAISE_FORMAT
"]u'", uid
);
135 printf(DELIMITER_CHAR
);
136 printf("\\Z" DELIMITER_CHAR
);
137 printf("\\h'\\n[" LEFT_WIDTH_FORMAT
"]u-(\\n[" WIDTH_FORMAT
"]u/2u)'",
140 printf(DELIMITER_CHAR
);
141 printf("\\h'\\n[" WIDTH_FORMAT
"]u'", uid
);
143 else if (output_format
== mathml
) {
144 printf("<mover accent='true'>");
151 void accent_box::check_tabs(int level
)
153 ab
->check_tabs(level
+ 1);
154 p
->check_tabs(level
+ 1);
157 void accent_box::debug_print()
159 fprintf(stderr
, "{ ");
161 fprintf(stderr
, " } accent { ");
163 fprintf(stderr
, " }");
166 class overline_char_box
175 overline_char_box::overline_char_box()
179 void overline_char_box::output()
181 if (output_format
== troff
) {
182 printf("\\v'-%dM/2u-%dM'", 7*default_rule_thickness
, x_height
);
183 printf((draw_flag
? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
185 printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness
, x_height
);
187 else if (output_format
== mathml
)
188 printf("<mo>¯</mo>");
191 void overline_char_box::debug_print()
193 fprintf(stderr
, "<overline char>");
201 int compute_metrics(int);
206 box
*make_overline_box(box
*p
)
209 return new accent_box(p
, new overline_char_box
);
211 return new overline_box(p
);
214 overline_box::overline_box(box
*pp
) : pointer_box(pp
)
218 int overline_box::compute_metrics(int style
)
220 int r
= p
->compute_metrics(cramped_style(style
));
222 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]+%dM\n",
223 uid
, p
->uid
, default_rule_thickness
*5);
224 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
225 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
229 void overline_box::output()
231 if (output_format
== troff
) {
233 printf("\\Z" DELIMITER_CHAR
);
234 printf("\\v'-\\n[" HEIGHT_FORMAT
"]u-(%dM/2u)'",
235 p
->uid
, 7*default_rule_thickness
);
237 printf("\\D'l\\n[" WIDTH_FORMAT
"]u 0'", p
->uid
);
239 printf("\\l'\\n[" WIDTH_FORMAT
"]u\\&\\(ru'", p
->uid
);
240 printf(DELIMITER_CHAR
);
243 else if (output_format
== mathml
) {
244 printf("<mover accent='false'>");
246 printf("<mo>¯</mo></mover>");
250 void overline_box::debug_print()
252 fprintf(stderr
, "{ ");
254 fprintf(stderr
, " } bar");
263 uaccent_box(box
*, box
*);
265 int compute_metrics(int);
267 void compute_subscript_kern();
268 void check_tabs(int);
272 box
*make_uaccent_box(box
*p
, box
*q
)
274 return new uaccent_box(p
, q
);
277 uaccent_box::uaccent_box(box
*pp
, box
*qq
)
278 : pointer_box(pp
), ab(qq
)
282 uaccent_box::~uaccent_box()
287 int uaccent_box::compute_metrics(int style
)
289 int r
= p
->compute_metrics(style
);
290 ab
->compute_metrics(style
);
291 printf(".nr " LEFT_WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]/2"
292 ">?(\\n[" WIDTH_FORMAT
"]/2)\n",
293 uid
, p
->uid
, ab
->uid
);
294 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]/2"
295 ">?(\\n[" WIDTH_FORMAT
"]/2)"
296 "+\\n[" LEFT_WIDTH_FORMAT
"]\n",
297 uid
, p
->uid
, ab
->uid
, uid
);
298 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
299 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]"
300 "+\\n[" DEPTH_FORMAT
"]\n",
301 uid
, p
->uid
, ab
->uid
);
303 printf(".nr " MARK_REG
" +\\n[" LEFT_WIDTH_FORMAT
"]"
304 "-(\\n[" WIDTH_FORMAT
"]/2)'\n",
309 void uaccent_box::output()
311 if (output_format
== troff
) {
312 printf("\\Z" DELIMITER_CHAR
);
313 printf("\\h'\\n[" LEFT_WIDTH_FORMAT
"]u-(\\n[" WIDTH_FORMAT
"]u/2u)'",
315 printf("\\v'\\n[" DEPTH_FORMAT
"]u'", p
->uid
);
317 printf(DELIMITER_CHAR
);
318 printf("\\Z" DELIMITER_CHAR
);
319 printf("\\h'\\n[" LEFT_WIDTH_FORMAT
"]u-(\\n[" WIDTH_FORMAT
"]u/2u)'",
322 printf(DELIMITER_CHAR
);
323 printf("\\h'\\n[" WIDTH_FORMAT
"]u'", uid
);
325 else if (output_format
== mathml
) {
326 printf("<munder accent='true'>");
333 void uaccent_box::check_tabs(int level
)
335 ab
->check_tabs(level
+ 1);
336 p
->check_tabs(level
+ 1);
339 void uaccent_box::compute_subscript_kern()
341 box::compute_subscript_kern(); // want 0 subscript kern
344 void uaccent_box::debug_print()
346 fprintf(stderr
, "{ ");
348 fprintf(stderr
, " } uaccent { ");
350 fprintf(stderr
, " }");
353 class underline_char_box
357 underline_char_box();
362 underline_char_box::underline_char_box()
366 void underline_char_box::output()
368 if (output_format
== troff
) {
369 printf("\\v'%dM/2u'", 7*default_rule_thickness
);
370 printf((draw_flag
? "\\D'l%dM 0'" : "\\l'%dM\\&\\(ru'"),
372 printf("\\v'-%dM/2u'", 7*default_rule_thickness
);
374 else if (output_format
== mathml
)
375 printf("<mo>_</mo>");
378 void underline_char_box::debug_print()
380 fprintf(stderr
, "<underline char>");
388 underline_box(box
*);
389 int compute_metrics(int);
391 void compute_subscript_kern();
395 box
*make_underline_box(box
*p
)
398 return new uaccent_box(p
, new underline_char_box
);
400 return new underline_box(p
);
403 underline_box::underline_box(box
*pp
) : pointer_box(pp
)
407 int underline_box::compute_metrics(int style
)
409 int r
= p
->compute_metrics(style
);
411 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]+%dM\n",
412 uid
, p
->uid
, default_rule_thickness
*5);
413 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
414 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
418 void underline_box::output()
420 if (output_format
== troff
) {
422 printf("\\Z" DELIMITER_CHAR
);
423 printf("\\v'\\n[" DEPTH_FORMAT
"]u+(%dM/2u)'",
424 p
->uid
, 7*default_rule_thickness
);
426 printf("\\D'l\\n[" WIDTH_FORMAT
"]u 0'", p
->uid
);
428 printf("\\l'\\n[" WIDTH_FORMAT
"]u\\&\\(ru'", p
->uid
);
429 printf(DELIMITER_CHAR
);
432 else if (output_format
== mathml
) {
433 printf("<munder accent='true'>");
435 printf("<mo>¯</mo></munder>");
439 // we want an underline box to have 0 subscript kern
441 void underline_box::compute_subscript_kern()
443 box::compute_subscript_kern();
446 void underline_box::debug_print()
448 fprintf(stderr
, "{ ");
450 fprintf(stderr
, " } under");
453 size_box::size_box(char *s
, box
*pp
) : pointer_box(pp
), size(s
)
457 int size_box::compute_metrics(int style
)
459 printf(".nr " SIZE_FORMAT
" \\n[.ps]\n", uid
);
460 printf(".ps %s\n", size
);
461 printf(".nr " SMALL_SIZE_FORMAT
" \\n[.ps]\n", uid
);
462 int r
= p
->compute_metrics(style
);
463 printf(".ps \\n[" SIZE_FORMAT
"]u\n", uid
);
464 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
465 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
466 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
470 void size_box::output()
472 if (output_format
== troff
) {
473 printf("\\s[\\n[" SMALL_SIZE_FORMAT
"]u]", uid
);
475 printf("\\s[\\n[" SIZE_FORMAT
"]u]", uid
);
477 else if (output_format
== mathml
) {
478 printf("<mstyle mathsize='%s'>", size
);
484 size_box::~size_box()
489 void size_box::debug_print()
491 fprintf(stderr
, "size %s { ", size
);
493 fprintf(stderr
, " }");
496 font_box::font_box(char *s
, box
*pp
) : pointer_box(pp
), f(s
)
500 font_box::~font_box()
505 int font_box::compute_metrics(int style
)
507 const char *old_roman_font
= current_roman_font
;
508 current_roman_font
= f
;
509 printf(".nr " FONT_FORMAT
" \\n[.f]\n", uid
);
510 printf(".ft %s\n", f
);
511 int r
= p
->compute_metrics(style
);
512 current_roman_font
= old_roman_font
;
513 printf(".ft \\n[" FONT_FORMAT
"]\n", uid
);
514 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
515 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
516 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
520 void font_box::output()
522 if (output_format
== troff
) {
523 printf("\\f[%s]", f
);
524 const char *old_roman_font
= current_roman_font
;
525 current_roman_font
= f
;
527 current_roman_font
= old_roman_font
;
528 printf("\\f[\\n[" FONT_FORMAT
"]]", uid
);
530 else if (output_format
== mathml
) {
531 const char *mlfont
= f
;
532 // bold and italic are already in MathML; translate eqn roman here
548 printf("<mstyle mathvariant='%s'>", mlfont
);
554 void font_box::debug_print()
556 fprintf(stderr
, "font %s { ", f
);
558 fprintf(stderr
, " }");
561 fat_box::fat_box(box
*pp
) : pointer_box(pp
)
565 int fat_box::compute_metrics(int style
)
567 int r
= p
->compute_metrics(style
);
568 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]+%dM\n",
569 uid
, p
->uid
, fat_offset
);
570 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
571 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
575 void fat_box::output()
577 if (output_format
== troff
) {
579 printf("\\h'-\\n[" WIDTH_FORMAT
"]u'", p
->uid
);
580 printf("\\h'%dM'", fat_offset
);
583 else if (output_format
== mathml
) {
584 printf("<mstyle mathvariant='double-struck'>");
590 void fat_box::debug_print()
592 fprintf(stderr
, "fat { ");
594 fprintf(stderr
, " }");
597 vmotion_box::vmotion_box(int i
, box
*pp
) : pointer_box(pp
), n(i
)
601 int vmotion_box::compute_metrics(int style
)
603 int r
= p
->compute_metrics(style
);
604 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
606 printf(".nr " HEIGHT_FORMAT
" %dM+\\n[" HEIGHT_FORMAT
"]\n",
608 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
611 printf(".nr " DEPTH_FORMAT
" %dM+\\n[" DEPTH_FORMAT
"]>?0\n",
613 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n",
619 void vmotion_box::output()
621 if (output_format
== troff
) {
622 printf("\\v'%dM'", -n
);
624 printf("\\v'%dM'", n
);
626 else if (output_format
== mathml
) {
627 printf("<merror>eqn vertical motion cannot be expressed "
628 "in MathML</merror>");
633 void vmotion_box::debug_print()
636 fprintf(stderr
, "up %d { ", n
);
638 fprintf(stderr
, "down %d { ", -n
);
640 fprintf(stderr
, " }");
643 hmotion_box::hmotion_box(int i
, box
*pp
) : pointer_box(pp
), n(i
)
647 int hmotion_box::compute_metrics(int style
)
649 int r
= p
->compute_metrics(style
);
650 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]+%dM\n",
652 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]\n", uid
, p
->uid
);
653 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]\n", uid
, p
->uid
);
655 printf(".nr " MARK_REG
" +%dM\n", n
);
659 void hmotion_box::output()
661 if (output_format
== troff
) {
662 printf("\\h'%dM'", n
);
665 else if (output_format
== mathml
) {
666 printf("<merror>eqn horizontal motion cannot be expessed "
667 "in MathML</merror>");
672 void hmotion_box::debug_print()
675 fprintf(stderr
, "fwd %d { ", n
);
677 fprintf(stderr
, "back %d { ", -n
);
679 fprintf(stderr
, " }");
682 vcenter_box::vcenter_box(box
*pp
) : pointer_box(pp
)
686 int vcenter_box::compute_metrics(int style
)
688 int r
= p
->compute_metrics(style
);
689 printf(".nr " WIDTH_FORMAT
" 0\\n[" WIDTH_FORMAT
"]\n", uid
, p
->uid
);
690 printf(".nr " SUP_RAISE_FORMAT
" \\n[" DEPTH_FORMAT
"]-\\n["
691 HEIGHT_FORMAT
"]/2+%dM\n",
692 uid
, p
->uid
, p
->uid
, axis_height
);
693 printf(".nr " HEIGHT_FORMAT
" \\n[" HEIGHT_FORMAT
"]+\\n["
694 SUP_RAISE_FORMAT
"]>?0\n", uid
, p
->uid
, uid
);
695 printf(".nr " DEPTH_FORMAT
" \\n[" DEPTH_FORMAT
"]-\\n["
696 SUP_RAISE_FORMAT
"]>?0\n", uid
, p
->uid
, uid
);
701 void vcenter_box::output()
703 if (output_format
== troff
)
704 printf("\\v'-\\n[" SUP_RAISE_FORMAT
"]u'", uid
);
706 if (output_format
== troff
)
707 printf("\\v'\\n[" SUP_RAISE_FORMAT
"]u'", uid
);
710 void vcenter_box::debug_print()
712 fprintf(stderr
, "vcenter { ");
714 fprintf(stderr
, " }");