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