Adapt src/pre-eqn (src/preproc/eqn)
[s-roff.git] / src / pre-eqn / other.cpp
blob85da14847c52b2e46cad4413bc387798f530d564
1 /*@
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
11 * 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
16 * for more details.
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.
23 #include "config.h"
24 #include "eqn-config.h"
26 #include "eqn.h"
27 #include "pbox.h"
29 class accent_box
30 : public pointer_box
32 box *ab;
34 public:
35 accent_box(box *, box *);
36 ~accent_box();
37 int compute_metrics(int);
38 void output();
39 void debug_print();
40 void check_tabs(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()
54 delete ab;
57 #if 0
58 int accent_box::compute_metrics(int style)
60 int r = p->compute_metrics(style);
61 p->compute_skew();
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",
69 uid, ab->uid, uid);
70 return r;
73 void accent_box::output()
75 if (output_format == troff) {
76 printf("\\h'\\n[" WIDTH_FORMAT "]u-\\n[" WIDTH_FORMAT "]u/2u+\\n["
77 SKEW_FORMAT "]u'",
78 p->uid, ab->uid, p->uid);
79 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
80 ab->output();
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["
84 SKEW_FORMAT "]u)'",
85 p->uid, ab->uid, p->uid);
86 p->output();
88 else if (output_format == mathml) {
89 printf("<mover accent='true'>");
90 p->output();
91 ab->output();
92 printf("</mover>")
95 #endif
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);
104 p->compute_skew();
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",
118 uid, ab->uid, uid);
119 if (r)
120 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
121 "-(\\n[" WIDTH_FORMAT "]/2)'\n",
122 uid, p->uid);
123 return r;
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);
134 ab->output();
135 printf(DELIMITER_CHAR);
136 printf("\\Z" DELIMITER_CHAR);
137 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
138 uid, p->uid);
139 p->output();
140 printf(DELIMITER_CHAR);
141 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
143 else if (output_format == mathml) {
144 printf("<mover accent='true'>");
145 p->output();
146 ab->output();
147 printf("</mover>");
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, "{ ");
160 p->debug_print();
161 fprintf(stderr, " } accent { ");
162 ab->debug_print();
163 fprintf(stderr, " }");
166 class overline_char_box
167 : public simple_box
169 public:
170 overline_char_box();
171 void output();
172 void debug_print();
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'"),
184 accent_width);
185 printf("\\v'%dM/2u+%dM'", 7*default_rule_thickness, x_height);
187 else if (output_format == mathml)
188 printf("<mo>&macr;</mo>");
191 void overline_char_box::debug_print()
193 fprintf(stderr, "<overline char>");
196 class overline_box
197 : public pointer_box
199 public:
200 overline_box(box *);
201 int compute_metrics(int);
202 void output();
203 void debug_print();
206 box *make_overline_box(box *p)
208 if (p->is_char())
209 return new accent_box(p, new overline_char_box);
210 else
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));
221 // 9
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);
226 return r;
229 void overline_box::output()
231 if (output_format == troff) {
232 // 9
233 printf("\\Z" DELIMITER_CHAR);
234 printf("\\v'-\\n[" HEIGHT_FORMAT "]u-(%dM/2u)'",
235 p->uid, 7*default_rule_thickness);
236 if (draw_flag)
237 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
238 else
239 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
240 printf(DELIMITER_CHAR);
241 p->output();
243 else if (output_format == mathml) {
244 printf("<mover accent='false'>");
245 p->output();
246 printf("<mo>&macr;</mo></mover>");
250 void overline_box::debug_print()
252 fprintf(stderr, "{ ");
253 p->debug_print();
254 fprintf(stderr, " } bar");
257 class uaccent_box
258 : public pointer_box
260 box *ab;
262 public:
263 uaccent_box(box *, box *);
264 ~uaccent_box();
265 int compute_metrics(int);
266 void output();
267 void compute_subscript_kern();
268 void check_tabs(int);
269 void debug_print();
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()
284 delete ab;
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);
302 if (r)
303 printf(".nr " MARK_REG " +\\n[" LEFT_WIDTH_FORMAT "]"
304 "-(\\n[" WIDTH_FORMAT "]/2)'\n",
305 uid, p->uid);
306 return r;
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)'",
314 uid, ab->uid);
315 printf("\\v'\\n[" DEPTH_FORMAT "]u'", p->uid);
316 ab->output();
317 printf(DELIMITER_CHAR);
318 printf("\\Z" DELIMITER_CHAR);
319 printf("\\h'\\n[" LEFT_WIDTH_FORMAT "]u-(\\n[" WIDTH_FORMAT "]u/2u)'",
320 uid, p->uid);
321 p->output();
322 printf(DELIMITER_CHAR);
323 printf("\\h'\\n[" WIDTH_FORMAT "]u'", uid);
325 else if (output_format == mathml) {
326 printf("<munder accent='true'>");
327 p->output();
328 ab->output();
329 printf("</munder>");
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, "{ ");
347 p->debug_print();
348 fprintf(stderr, " } uaccent { ");
349 ab->debug_print();
350 fprintf(stderr, " }");
353 class underline_char_box
354 : public simple_box
356 public:
357 underline_char_box();
358 void output();
359 void debug_print();
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'"),
371 accent_width);
372 printf("\\v'-%dM/2u'", 7*default_rule_thickness);
374 else if (output_format == mathml)
375 printf("<mo>&lowbar;</mo>");
378 void underline_char_box::debug_print()
380 fprintf(stderr, "<underline char>");
384 class underline_box
385 : public pointer_box
387 public:
388 underline_box(box *);
389 int compute_metrics(int);
390 void output();
391 void compute_subscript_kern();
392 void debug_print();
395 box *make_underline_box(box *p)
397 if (p->is_char())
398 return new uaccent_box(p, new underline_char_box);
399 else
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);
410 // 10
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);
415 return r;
418 void underline_box::output()
420 if (output_format == troff) {
421 // 10
422 printf("\\Z" DELIMITER_CHAR);
423 printf("\\v'\\n[" DEPTH_FORMAT "]u+(%dM/2u)'",
424 p->uid, 7*default_rule_thickness);
425 if (draw_flag)
426 printf("\\D'l\\n[" WIDTH_FORMAT "]u 0'", p->uid);
427 else
428 printf("\\l'\\n[" WIDTH_FORMAT "]u\\&\\(ru'", p->uid);
429 printf(DELIMITER_CHAR);
430 p->output();
432 else if (output_format == mathml) {
433 printf("<munder accent='true'>");
434 p->output();
435 printf("<mo>&macr;</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, "{ ");
449 p->debug_print();
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);
467 return r;
470 void size_box::output()
472 if (output_format == troff) {
473 printf("\\s[\\n[" SMALL_SIZE_FORMAT "]u]", uid);
474 p->output();
475 printf("\\s[\\n[" SIZE_FORMAT "]u]", uid);
477 else if (output_format == mathml) {
478 printf("<mstyle mathsize='%s'>", size);
479 p->output();
480 printf("</mstyle>");
484 size_box::~size_box()
486 a_delete size;
489 void size_box::debug_print()
491 fprintf(stderr, "size %s { ", size);
492 p->debug_print();
493 fprintf(stderr, " }");
496 font_box::font_box(char *s, box *pp) : pointer_box(pp), f(s)
500 font_box::~font_box()
502 a_delete f;
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);
517 return r;
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;
526 p->output();
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
533 switch (f[0]) {
534 case 'I':
535 case 'i':
536 mlfont = "italic";
537 break;
538 case 'B':
539 case 'b':
540 mlfont = "bold";
541 break;
542 case 'R':
543 case 'r':
544 default:
545 mlfont = "normal";
546 break;
548 printf("<mstyle mathvariant='%s'>", mlfont);
549 p->output();
550 printf("</mstyle>");
554 void font_box::debug_print()
556 fprintf(stderr, "font %s { ", f);
557 p->debug_print();
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);
572 return r;
575 void fat_box::output()
577 if (output_format == troff) {
578 p->output();
579 printf("\\h'-\\n[" WIDTH_FORMAT "]u'", p->uid);
580 printf("\\h'%dM'", fat_offset);
581 p->output();
583 else if (output_format == mathml) {
584 printf("<mstyle mathvariant='double-struck'>");
585 p->output();
586 printf("</mstyle>");
590 void fat_box::debug_print()
592 fprintf(stderr, "fat { ");
593 p->debug_print();
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);
605 if (n > 0) {
606 printf(".nr " HEIGHT_FORMAT " %dM+\\n[" HEIGHT_FORMAT "]\n",
607 uid, n, p->uid);
608 printf(".nr " DEPTH_FORMAT " \\n[" DEPTH_FORMAT "]\n", uid, p->uid);
610 else {
611 printf(".nr " DEPTH_FORMAT " %dM+\\n[" DEPTH_FORMAT "]>?0\n",
612 uid, -n, p->uid);
613 printf(".nr " HEIGHT_FORMAT " \\n[" HEIGHT_FORMAT "]\n",
614 uid, p->uid);
616 return r;
619 void vmotion_box::output()
621 if (output_format == troff) {
622 printf("\\v'%dM'", -n);
623 p->output();
624 printf("\\v'%dM'", n);
626 else if (output_format == mathml) {
627 printf("<merror>eqn vertical motion cannot be expressed "
628 "in MathML</merror>");
629 p->output();
633 void vmotion_box::debug_print()
635 if (n >= 0)
636 fprintf(stderr, "up %d { ", n);
637 else
638 fprintf(stderr, "down %d { ", -n);
639 p->debug_print();
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",
651 uid, p->uid, 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);
654 if (r)
655 printf(".nr " MARK_REG " +%dM\n", n);
656 return r;
659 void hmotion_box::output()
661 if (output_format == troff) {
662 printf("\\h'%dM'", n);
663 p->output();
665 else if (output_format == mathml) {
666 printf("<merror>eqn horizontal motion cannot be expessed "
667 "in MathML</merror>");
668 p->output();
672 void hmotion_box::debug_print()
674 if (n >= 0)
675 fprintf(stderr, "fwd %d { ", n);
676 else
677 fprintf(stderr, "back %d { ", -n);
678 p->debug_print();
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);
698 return r;
701 void vcenter_box::output()
703 if (output_format == troff)
704 printf("\\v'-\\n[" SUP_RAISE_FORMAT "]u'", uid);
705 p->output();
706 if (output_format == troff)
707 printf("\\v'\\n[" SUP_RAISE_FORMAT "]u'", uid);
710 void vcenter_box::debug_print()
712 fprintf(stderr, "vcenter { ");
713 p->debug_print();
714 fprintf(stderr, " }");
717 // s-it2-mode