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