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