]> git.lyx.org Git - features.git/blob - src/mathed/array.C
multicell selection
[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 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
79 void MathArray::substitute(MathMacro const & m)
80 {
81         MathArray tmp;
82         for (int pos = 0; pos < size(); next(pos)) {
83                 if (isInset(pos)) 
84                         nextInset(pos)->substitute(tmp, m);
85                 else 
86                         tmp.push_back(GetChar(pos), GetCode(pos));
87         }
88         swap(tmp);
89 }
90
91
92 MathArray & MathArray::operator=(MathArray const & array)
93 {
94         MathArray tmp(array);
95         swap(tmp);
96         return *this;
97 }
98
99
100 MathInset * MathArray::nextInset(int pos) const
101 {
102         if (!isInset(pos))
103                 return 0;
104         MathInset * p;
105         memcpy(&p, &bf_[0] + pos + 1, sizeof(p));
106         return p;
107 }
108
109 MathInset * MathArray::prevInset(int pos) const
110 {
111         if (!pos)
112                 return 0;
113         prev(pos);
114         return nextInset(pos);
115 }
116
117 unsigned char MathArray::GetChar(int pos) const
118 {
119         return pos < size() ? bf_[pos + 1] : '\0';
120 }
121
122 string MathArray::GetString(int & pos) const
123 {
124         string s;
125         if (isInset(pos))
126                 return s;
127
128         MathTextCodes const fcode = GetCode(pos);
129         do {
130                 s += GetChar(pos);
131                 next(pos);
132         } while (pos < size() && !isInset(pos) && GetCode(pos) == fcode);
133
134         return s;
135 }
136
137 MathTextCodes MathArray::GetCode(int pos) const
138 {
139         return pos < size() ? MathTextCodes(bf_[pos]) : LM_TC_MIN;
140 }
141
142 void MathArray::setCode(int pos, MathTextCodes t)
143 {
144         if (pos > size() || isInset(pos))
145                 return;
146         bf_[pos] = t;
147         bf_[pos + 2] = t;
148 }
149
150 void MathArray::insert(int pos, MathInset * p)
151 {
152         bf_.insert(bf_.begin() + pos, 2 + sizeof(p), LM_TC_INSET);
153         memcpy(&bf_[pos + 1], &p, sizeof(p));
154 }
155
156
157 void MathArray::replace(int pos, MathInset * p)
158 {
159         memcpy(&bf_[pos + 1], &p, sizeof(p));
160 }
161
162 void MathArray::insert(int pos, unsigned char b, MathTextCodes t)
163 {
164         bf_.insert(bf_.begin() + pos, 3, t);
165         bf_[pos + 1] = b;
166 }
167
168
169 void MathArray::insert(int pos, MathArray const & array)
170 {
171         bf_.insert(bf_.begin() + pos, array.bf_.begin(), array.bf_.end());
172         for (int p = pos; p < pos + array.size(); next(p)) 
173                 if (isInset(p)) 
174                         replace(p, nextInset(p)->clone());
175 }
176
177
178 void MathArray::push_back(MathInset * p)
179 {       
180         insert(size(), p);
181 }
182
183 void MathArray::push_back(unsigned char b, MathTextCodes c)
184 {
185         insert(size(), b, c);
186 }
187
188 void MathArray::push_back(MathArray const & array)
189 {
190         insert(size(), array);
191 }
192
193
194
195 void MathArray::clear()
196 {
197         bf_.clear();
198 }
199
200
201 void MathArray::swap(MathArray & array)
202 {
203         if (this != &array) 
204                 bf_.swap(array.bf_);
205 }
206
207
208 bool MathArray::empty() const
209 {
210         return bf_.empty();
211 }
212    
213
214 int MathArray::size() const
215 {
216         return bf_.size();
217 }
218
219
220 void MathArray::erase()
221 {
222         erase(0, size());
223 }
224
225
226 void MathArray::erase(int pos)
227 {
228         if (pos < static_cast<int>(bf_.size()))
229                 erase(pos, pos + item_size(pos));
230 }
231
232
233 void MathArray::erase(int pos1, int pos2)
234 {
235         bf_.erase(bf_.begin() + pos1, bf_.begin() + pos2);
236 }
237
238
239 bool MathArray::isInset(int pos) const
240 {
241         if (pos >= size())
242                 return false;
243         return MathIsInset(bf_[pos]);
244 }
245
246
247 MathInset * MathArray::back_inset() const
248 {
249         if (!empty()) {
250                 int pos = size();
251                 prev(pos);
252                 if (isInset(pos))
253                         return nextInset(pos);
254         }
255         return 0;
256 }
257
258
259 void MathArray::dump2(ostream & os) const
260 {
261         for (buffer_type::const_iterator it = bf_.begin(); it != bf_.end(); ++it)
262                 os << int(*it) << ' ';
263         os << endl;
264 }
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