14a8ffb1a14d651bb13dac8f53f198c85ccdafb6
[platform/upstream/groff.git] / src / preproc / eqn / special.cpp
1 // -*- C++ -*-
2 /* Copyright (C) 1989-2014  Free Software Foundation, Inc.
3      Written by James Clark (jjc@jclark.com)
4
5 This file is part of groff.
6
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.
11
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
15 for more details.
16
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/>. */
19
20 #include "eqn.h"
21 #include "pbox.h"
22
23 #define STRING_FORMAT PREFIX "str%d"
24
25 #define SPECIAL_STRING "0s"
26 #define SPECIAL_WIDTH_REG "0w"
27 #define SPECIAL_HEIGHT_REG "0h"
28 #define SPECIAL_DEPTH_REG "0d"
29 #define SPECIAL_SUB_KERN_REG "0skern"
30 #define SPECIAL_SKEW_REG "0skew"
31
32 /*
33 For example:
34
35 .de Cl
36 .ds 0s \Z'\\*[0s]'\v'\\n(0du'\D'l \\n(0wu -\\n(0hu-\\n(0du'\v'\\n(0hu'
37 ..
38 .EQ
39 define cancel 'special Cl'
40 .EN
41 */
42
43
44 class special_box : public pointer_box {
45   char *macro_name;
46 public:
47   special_box(char *, box *);
48   ~special_box();
49   int compute_metrics(int);
50   void compute_subscript_kern();
51   void compute_skew();
52   void output();
53   void debug_print();
54 };
55
56 box *make_special_box(char *s, box *p)
57 {
58   return new special_box(s, p);
59 }
60
61 special_box::special_box(char *s, box *pp) : pointer_box(pp), macro_name(s)
62 {
63 }
64
65 special_box::~special_box()
66 {
67   a_delete macro_name;
68 }
69
70 int special_box::compute_metrics(int style)
71 {
72   int r = p->compute_metrics(style);
73   p->compute_subscript_kern();
74   p->compute_skew();
75   printf(".ds " SPECIAL_STRING " \"");
76   p->output();
77   printf("\n");
78   printf(".nr " SPECIAL_WIDTH_REG " 0\\n[" WIDTH_FORMAT "]\n", p->uid);
79   printf(".nr " SPECIAL_HEIGHT_REG " \\n[" HEIGHT_FORMAT "]\n", p->uid);
80   printf(".nr " SPECIAL_DEPTH_REG " \\n[" DEPTH_FORMAT "]\n", p->uid);
81   printf(".nr " SPECIAL_SUB_KERN_REG " \\n[" SUB_KERN_FORMAT "]\n", p->uid);
82   printf(".nr " SPECIAL_SKEW_REG " 0\\n[" SKEW_FORMAT "]\n", p->uid);
83   printf(".%s\n", macro_name);
84   printf(".rn " SPECIAL_STRING " " STRING_FORMAT "\n", uid);
85   printf(".nr " WIDTH_FORMAT " 0\\n[" SPECIAL_WIDTH_REG "]\n", uid);
86   printf(".nr " HEIGHT_FORMAT " 0>?\\n[" SPECIAL_HEIGHT_REG "]\n", uid);
87   printf(".nr " DEPTH_FORMAT " 0>?\\n[" SPECIAL_DEPTH_REG "]\n", uid);
88   printf(".nr " SUB_KERN_FORMAT " 0>?\\n[" SPECIAL_SUB_KERN_REG "]\n", uid);
89   printf(".nr " SKEW_FORMAT " 0\\n[" SPECIAL_SKEW_REG "]\n", uid);
90   // User will have to change MARK_REG if appropriate.
91   return r;
92 }
93
94 void special_box::compute_subscript_kern()
95 {
96   // Already computed in compute_metrics(), so do nothing.
97 }
98
99 void special_box::compute_skew()
100 {
101   // Already computed in compute_metrics(), so do nothing.
102 }
103
104 void special_box::output()
105 {
106   if (output_format == troff)
107     printf("\\*[" STRING_FORMAT "]", uid);
108   else if (output_format == mathml)
109     printf("<merror>eqn specials cannot be expressed in MathML</merror>");
110 }
111
112 void special_box::debug_print()
113 {
114   fprintf(stderr, "special %s { ", macro_name);
115   p->debug_print();
116   fprintf(stderr, " }");
117 }