]> git.lyx.org Git - features.git/blob - src/mathed/array.C
prepare re-enabling LaTeX feature validation
[features.git] / src / mathed / array.C
1
2 #ifdef __GNUG__
3 #pragma implementation
4 #endif
5
6 #include "math_inset.h"
7 #include "debug.h"
8 #include "array.h"
9 #include "math_scriptinset.h"
10 #include "math_parser.h"
11 #include "mathed/support.h"
12
13 using std::ostream;
14 using std::endl;
15
16 MathArray::MathArray()
17 {}
18
19
20 MathArray::~MathArray()
21 {
22         for (int pos = 0; pos < size(); next(pos)) 
23                 if (MathIsInset(pos)) 
24                         delete nextInset(pos);
25 }
26
27
28 MathArray::MathArray(MathArray const & array)
29         : bf_(array.bf_)
30 {
31         for (int pos = 0; pos < size(); next(pos)) 
32                 if (isInset(pos)) 
33                         replace(pos, nextInset(pos)->clone());
34 }
35
36
37 bool MathArray::next(int & pos) const
38 {
39         if (pos >= size() - 1)
40                 return false;
41
42         pos += item_size(pos);
43         return true;
44 }
45
46
47 bool MathArray::prev(int & pos) const
48 {
49         if (pos == 0)
50                 return false;
51
52         pos -= item_size(pos - 1);
53         return true;
54 }
55
56
57 bool MathArray::last(int & pos) const
58 {
59         pos = bf_.size();
60         return prev(pos);
61 }
62
63
64 int MathArray::item_size(int pos) const
65 {
66         return 2 + (isInset(pos) ? sizeof(MathInset*) : 1);
67 }
68                 
69
70
71 void MathArray::substitute(MathMacro const & m)
72 {
73         MathArray tmp;
74         for (int pos = 0; pos < size(); next(pos)) {
75                 if (isInset(pos)) 
76                         nextInset(pos)->substitute(tmp, m);
77                 else 
78                         tmp.push_back(GetChar(pos), GetCode(pos));
79         }
80         swap(tmp);
81 }
82
83
84 MathArray & MathArray::operator=(MathArray const & array)
85 {
86         MathArray tmp(array);
87         swap(tmp);
88         return *this;
89 }
90
91
92 MathInset * MathArray::nextInset(int pos) const
93 {
94         if (!isInset(pos))
95                 return 0;
96         MathInset * p;
97         memcpy(&p, &bf_[0] + pos + 1, sizeof(p));
98         return p;
99 }
100
101 MathInset * MathArray::prevInset(int pos) const
102 {
103         if (!pos)
104                 return 0;
105         prev(pos);
106         return nextInset(pos);
107 }
108
109 unsigned char MathArray::GetChar(int pos) const
110 {
111         return pos < size() ? bf_[pos + 1] : '\0';
112 }
113
114 string MathArray::GetString(int & pos) const
115 {
116         string s;
117         if (isInset(pos))
118                 return s;
119
120         MathTextCodes const fcode = GetCode(pos);
121         do {
122                 s += GetChar(pos);
123                 next(pos);
124         } while (pos < size() && !isInset(pos) && GetCode(pos) == fcode);
125
126         return s;
127 }
128
129 MathTextCodes MathArray::GetCode(int pos) const
130 {
131         return pos < size() ? MathTextCodes(bf_[pos]) : LM_TC_MIN;
132 }
133
134 void MathArray::setCode(int pos, MathTextCodes t)
135 {
136         if (pos > size() || isInset(pos))
137                 return;
138         bf_[pos] = t;
139         bf_[pos + 2] = t;
140 }
141
142 void MathArray::insert(int pos, MathInset * p)
143 {
144         bf_.insert(bf_.begin() + pos, 2 + sizeof(p), LM_TC_INSET);
145         memcpy(&bf_[pos + 1], &p, sizeof(p));
146 }
147
148
149 void MathArray::replace(int pos, MathInset * p)
150 {
151         memcpy(&bf_[pos + 1], &p, sizeof(p));
152 }
153
154 void MathArray::insert(int pos, unsigned char b, MathTextCodes t)
155 {
156         bf_.insert(bf_.begin() + pos, 3, t);
157         bf_[pos + 1] = b;
158 }
159
160
161 void MathArray::insert(int pos, MathArray const & array)
162 {
163         bf_.insert(bf_.begin() + pos, array.bf_.begin(), array.bf_.end());
164         for (int p = pos; p < pos + array.size(); next(p)) 
165                 if (isInset(p)) 
166                         replace(p, nextInset(p)->clone());
167 }
168
169
170 void MathArray::push_back(MathInset * p)
171 {       
172         insert(size(), p);
173 }
174
175 void MathArray::push_back(unsigned char b, MathTextCodes c)
176 {
177         insert(size(), b, c);
178 }
179
180 void MathArray::push_back(MathArray const & array)
181 {
182         insert(size(), array);
183 }
184
185
186
187 void MathArray::clear()
188 {
189         bf_.clear();
190 }
191
192
193 void MathArray::swap(MathArray & array)
194 {
195         if (this != &array) 
196                 bf_.swap(array.bf_);
197 }
198
199
200 bool MathArray::empty() const
201 {
202         return bf_.empty();
203 }
204    
205
206 int MathArray::size() const
207 {
208         return bf_.size();
209 }
210
211
212 void MathArray::erase(int pos)
213 {
214         if (pos < static_cast<int>(bf_.size()))
215                 erase(pos, pos + item_size(pos));
216 }
217
218
219 void MathArray::erase(int pos1, int pos2)
220 {
221         bf_.erase(bf_.begin() + pos1, bf_.begin() + pos2);
222 }
223
224
225 bool MathArray::isInset(int pos) const
226 {
227         if (pos >= size())
228                 return false;
229         return MathIsInset(bf_[pos]);
230 }
231
232
233 MathInset * MathArray::back_inset() const
234 {
235         if (!empty()) {
236                 int pos = size();
237                 prev(pos);
238                 if (isInset(pos))
239                         return nextInset(pos);
240         }
241         return 0;
242 }
243
244
245 void MathArray::dump2(ostream & os) const
246 {
247         for (buffer_type::const_iterator it = bf_.begin(); it != bf_.end(); ++it)
248                 os << int(*it) << ' ';
249         os << endl;
250 }
251
252
253
254 void MathArray::dump(ostream & os) const
255 {
256         for (int pos = 0; pos < size(); next(pos)) {
257                 if (isInset(pos)) 
258                         os << "<inset: " << nextInset(pos) << ">";
259                 else 
260                         os << "<" << int(bf_[pos]) << " " << int(bf_[pos+1]) << ">";
261         }
262 }
263
264
265 std::ostream & operator<<(std::ostream & os, MathArray const & ar)
266 {
267         ar.dump2(os);
268         return os;
269 }
270
271
272 void MathArray::Write(ostream & os, bool fragile) const
273 {
274         if (empty())
275                 return;
276
277         int brace = 0;
278         
279         for (int pos = 0; pos < size(); next(pos)) {
280                 if (isInset(pos)) {
281
282                         nextInset(pos)->Write(os, fragile);
283
284                 } else {
285
286                         MathTextCodes fcode = GetCode(pos);
287                         unsigned char c = GetChar(pos);
288
289                         if (MathIsSymbol(fcode)) {
290                                 latexkeys const * l = lm_get_key_by_id(c, LM_TK_SYM);
291
292                                 if (l == 0) {
293                                         l = lm_get_key_by_id(c, LM_TK_BIGSYM);
294                                 }
295
296                                 if (l) {
297                                         os << '\\' << l->name << ' ';
298                                 } else {
299                                         lyxerr << "Could not find the LaTeX name for  " << c << " and fcode " << fcode << "!" << std::endl;
300                                 }
301                         } else {
302                                 if (fcode >= LM_TC_RM && fcode <= LM_TC_TEXTRM) 
303                                         os << '\\' << math_font_name[fcode - LM_TC_RM] << '{';
304
305                                 // Is there a standard logical XOR?
306                                 if ((fcode == LM_TC_TEX && c != '{' && c != '}') ||
307                                                 (fcode == LM_TC_SPECIAL))
308                                         os << '\\';
309                                 else {
310                                         if (c == '{')
311                                                 ++brace;
312                                         if (c == '}')
313                                                 --brace;
314                                 }
315                                 if (c == '}' && fcode == LM_TC_TEX && brace < 0) 
316                                         lyxerr <<"Math warning: Unexpected closing brace.\n";
317                                 else           
318                                         os << c;
319                         }
320
321                         if (fcode >= LM_TC_RM && fcode <= LM_TC_TEXTRM)
322                                 os << '}';
323                         
324                 }
325         }
326
327         if (brace > 0)
328                 os << string(brace, '}');
329 }
330
331
332 void MathArray::WriteNormal(ostream & os) const
333 {
334         if (empty()) {
335                 os << "[par] ";
336                 return;
337         }
338
339         Write(os, true);
340 }
341
342
343 void MathArray::Validate(LaTeXFeatures & features) const
344 {
345         for (int pos = 0; pos < size(); next(pos)) 
346                 if (isInset(pos)) 
347                         nextInset(pos)->Validate(features);
348 }
349