]> git.lyx.org Git - features.git/blob - src/mathed/math_extern.C
forgotten file math_extern[Ch]
[features.git] / src / mathed / math_extern.C
1
2 // This file contains most of the magic that extracts "context
3 // information" from the unstructered layout-oriented stuff in an
4 // MathArray.
5
6
7 #include "math_charinset.h"
8 #include "math_deliminset.h"
9 #include "math_exfuncinset.h"
10 #include "math_funcinset.h"
11 #include "math_matrixinset.h"
12 #include "math_mathmlstream.h"
13 #include "math_scriptinset.h"
14 #include "math_stringinset.h"
15 #include "debug.h"
16
17
18 std::ostream & operator<<(ostream & os, MathArray const & ar)
19 {
20         NormalStream ws(os);    
21         ws << ar;
22         return os;
23 }
24
25
26 MathScriptInset const * asScript(MathArray::const_iterator it)
27 {
28         if (it->nucleus()->asScriptInset())
29                 return 0;
30         ++it;
31         if (!it->nucleus())
32                 return 0;
33         return it->nucleus()->asScriptInset();
34 }
35
36
37
38 // returns sequence of char with same code starting at it up to end
39 // it might be less, though...
40 string charSequence(MathArray::const_iterator it, MathArray::const_iterator end)
41 {
42         string s;
43         MathCharInset const * p = it->nucleus()->asCharInset();
44         if (p) {
45                 for (MathTextCodes c = p->code(); it != end; ++it) {
46                         if (!it->nucleus())
47                                 break;
48                         p = it->nucleus()->asCharInset();
49                         if (!p || p->code() != c)
50                                 break;
51                         s += p->getChar();
52                 }
53         }
54         return s;
55 }
56
57
58 void glueChars(MathArray & dat)
59 {
60         MathArray ar;
61         MathArray::const_iterator it = dat.begin();
62         while (it != dat.end()) {
63                 if (it->nucleus() && it->nucleus()->asCharInset()) {
64                         string s = charSequence(it, dat.end());
65                         MathTextCodes c = it->nucleus()->asCharInset()->code();
66                         ar.push_back(MathAtom(new MathStringInset(s, c)));
67                         it += s.size();
68                 } else {
69                         ar.push_back(*it);
70                         ++it;
71                 }
72         }
73         ar.swap(dat);
74 }
75
76
77 bool needAsterisk(MathAtom const &, MathAtom const &)
78 {
79         return false;
80 }
81
82
83 void guessAsterisks(MathArray & dat)
84 {
85         if (dat.size() <= 1)
86                 return;
87         MathArray ar;
88         ar.push_back(*dat.begin());
89         MathArray::const_iterator it = dat.begin();
90         MathArray::const_iterator jt = it + 1;
91         for (; jt != dat.end(); ++it, ++jt) {
92                 if (needAsterisk(*it, *jt))
93                         ar.push_back(MathAtom(new MathCharInset('*')));
94                 ar.push_back(*it);
95         }
96         ar.push_back(*dat.end());
97         ar.swap(dat);
98 }
99
100
101 MathInset * singleItem(MathArray & ar)
102 {
103         lyxerr << "ar.size: " << ar.size() << "\n";
104         //lyxerr << "ar.begin: " << ar.begin() << "\n";
105         //lyxerr << "ar.nuc: " << ar.begin()->nucleus() << "\n";
106         lyxerr << "ar.nuc: " << *ar.begin()->nucleus() << "\n";
107         return ar.size() == 1 ? ar.begin()->nucleus() : 0;
108 }
109
110
111 void extractMatrices(MathArray & ar)
112 {
113         for (MathArray::iterator it = ar.begin(); it != ar.end(); ++it) {
114                 if (!it->nucleus())
115                         continue;       
116                 MathDelimInset * del = it->nucleus()->asDelimInset();
117                 if (!del)
118                         continue;
119                 MathInset * arr = singleItem(del->cell(0));
120                 if (!arr || !arr->asArrayInset())
121                         continue;
122                 *it = MathAtom(new MathMatrixInset(*(arr->asArrayInset())));
123         }
124
125
126
127 void extractDelims(MathArray & ar) {
128         // use indices rather than iterators for the loop  because we are going
129         // to modify the array.
130         for (MathArray::size_type i = 0; i < ar.size(); ++i) {
131                 MathArray::iterator it = ar.begin() + i;
132                 if (!it->nucleus())
133                         continue;       
134                 if ((*it)->getChar() != '(')
135                         continue;
136
137                 // search last closing paranthesis
138                 MathArray::iterator et = ar.end();
139                 for (MathArray::iterator jt = it + 1; jt != ar.end(); ++jt)
140                         if ((*jt)->getChar() == ')')
141                                 et = jt;
142                 if (et == ar.end())
143                         continue;
144
145                 // create a proper deliminset
146                 MathAtom at(new MathDelimInset("(", ")"));
147                 at->cell(0) = MathArray(it + 1, et);
148
149                 // replace the original stuff by the new inset
150                 ar.erase(it + 1, et + 1);
151                 *it = at;
152         }
153
154
155
156 // assume 'extractDelims' ran before
157 void extractFunctions(MathArray & ar)
158 {
159         // we need at least two items...
160         if (ar.size() <= 1)
161                 return;
162
163         for (MathArray::size_type i = 0; i < ar.size() - 1; ++i) {
164                 MathArray::iterator it = ar.begin() + i;
165
166                 // is this a function name?
167                 if (!it->nucleus())
168                         continue;       
169                 MathFuncInset * func = (*it)->asFuncInset();
170                 if (!func)
171                         continue;
172
173                 // do we have an exponent?
174                 // simply skippping the postion does the right thing:
175                 // 'sin' '^2' 'x' -> 'sin(x)' '^2'
176                 MathArray::iterator jt = it + 1;
177                 if (MathScriptInset * script = (*jt)->asScriptInset()) {
178                         // allow superscripts only
179                         if (script->hasDown())
180                                 continue;
181                         ++jt;
182                         if (jt == ar.end())
183                                 continue;
184                 }
185
186                 // jt points now to the "argument". Since we had run "extractDelims"
187                 // before, this could be a single argument only. Get hold of this.
188                 MathArray arg;
189                 MathDelimInset * del = (*jt)->asDelimInset();
190                 if (del && del->isParanthesis()) 
191                         arg = del->cell(0);
192                 else
193                         arg.push_back(*jt);
194
195                 // replace the function name by a real function inset
196                 (*it).reset(new MathExFuncInset(func->name(), arg));
197                 
198                 // remove the source of the argument from the array
199                 ar.erase(jt);
200         }
201
202
203
204 void extractStructure(MathArray & ar)
205 {
206         glueChars(ar);
207         extractMatrices(ar);
208         extractDelims(ar);
209         extractFunctions(ar);
210 }
211
212
213 void write(MathArray const & dat, WriteStream & wi)
214 {
215         MathArray ar = dat;
216         glueChars(ar);
217         for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
218                 MathInset const * p = it->nucleus();
219                 if (it + 1 != ar.end()) {
220                         if (MathScriptInset const * q = asScript(it)) {
221                                 q->write(p, wi);
222                                 ++it;
223                                 continue;
224                         } 
225                 }
226                 p->write(wi);
227         }
228 }
229
230
231 void normalize(MathArray const & dat, NormalStream & os)
232 {
233         MathArray ar = dat;
234         glueChars(ar);
235         for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
236                 MathInset const * p = it->nucleus();
237                 if (it + 1 != ar.end()) {
238                         if (MathScriptInset const * q = asScript(it)) {
239                                 q->normalize(p, os);
240                                 ++it;   
241                                 continue;
242                         }
243                 }
244                 p->normalize(os);
245         }
246 }
247
248
249 void octavize(MathArray const & dat, OctaveStream & os)
250 {
251         MathArray ar = dat;
252         extractStructure(ar);
253         for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
254                 MathInset const * p = it->nucleus();
255                 if (it + 1 != ar.end()) {
256                         if (MathScriptInset const * q = asScript(it)) {
257                                 q->octavize(p, os);
258                                 ++it;   
259                                 continue;
260                         }
261                 }
262                 p->octavize(os);
263         }
264 }
265
266
267 void maplize(MathArray const & dat, MapleStream & os)
268 {
269         MathArray ar = dat;
270         extractStructure(ar);
271         for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
272                 MathInset const * p = it->nucleus();
273                 if (it + 1 != ar.end()) {
274                         if (MathScriptInset const * q = asScript(it)) {
275                                 q->maplize(p, os);
276                                 ++it;   
277                                 continue;
278                         }
279                 }
280                 p->maplize(os);
281         }
282 }
283
284
285 void mathmlize(MathArray const & dat, MathMLStream & os)
286 {
287         MathArray ar = dat;
288         extractStructure(ar);
289         if (ar.size() == 0)
290                 os << "<mrow/>";
291         else if (ar.size() == 1)
292                 os << ar.begin()->nucleus();
293         else {
294                 os << MTag("mrow");
295                 for (MathArray::const_iterator it = ar.begin(); it != ar.end(); ++it) {
296                         MathInset const * p = it->nucleus();
297                         if (it + 1 != ar.end()) {
298                                 if (MathScriptInset const * q = asScript(it)) {
299                                         q->mathmlize(p, os);
300                                         ++it;   
301                                         continue;
302                                 }
303                         }
304                         p->mathmlize(os);
305                 }
306                 os << ETag("mrow");
307         }
308 }
309