]> git.lyx.org Git - features.git/blob - src/mathed/array.C
LyX Drinkers Union: patch 1
[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 namespace std;
16
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 GetInset(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, GetInset(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                         GetInset(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::GetInset(int pos) const
95 {
96         if (!isInset(pos))
97                 return 0;
98         MathInset * p;
99         memcpy(&p, bf_.begin() + pos + 1, sizeof(p));
100         return p;
101 }
102
103 char MathArray::GetChar(int pos) const
104 {
105         return pos < size() ? bf_[pos + 1] : '\0';
106 }
107
108 MathTextCodes MathArray::GetCode(int pos) const
109 {
110         return pos < size() ? MathTextCodes(bf_[pos]) : LM_TC_MIN;
111 }
112
113 void MathArray::insert(int pos, MathInset * p)
114 {
115         bf_.insert(bf_.begin() + pos, 2 + sizeof(p), LM_TC_INSET);
116         memcpy(&bf_[pos + 1], &p, sizeof(p));
117 }
118
119
120 void MathArray::replace(int pos, MathInset * p)
121 {
122         memcpy(&bf_[pos + 1], &p, sizeof(p));
123 }
124
125 void MathArray::insert(int pos, char b, MathTextCodes t)
126 {
127         bf_.insert(bf_.begin() + pos, 3, t);
128         bf_[pos + 1] = b;
129 }
130
131
132 void MathArray::insert(int pos, MathArray const & array)
133 {
134 #ifdef WITH_WARNINGS
135 #warning quick and really dirty: make sure that we really own our insets
136 #endif
137         MathArray a = array;
138         bf_.insert(bf_.begin() + pos, a.bf_.begin(), a.bf_.end());
139 }
140
141
142 void MathArray::push_back(MathInset * p)
143 {       
144         insert(size(), p);
145 }
146
147 void MathArray::push_back(char b, MathTextCodes c)
148 {
149         insert(size(), b, c);
150 }
151
152 void MathArray::push_back(MathArray const & array)
153 {
154         insert(size(), array);
155 }
156
157
158
159 void MathArray::clear()
160 {
161         bf_.clear();
162 }
163
164
165 void MathArray::swap(MathArray & array)
166 {
167         if (this != &array) 
168                 bf_.swap(array.bf_);
169 }
170
171
172 bool MathArray::empty() const
173 {
174         return bf_.empty();
175 }
176    
177
178 int MathArray::size() const
179 {
180         return bf_.size();
181 }
182
183
184 void MathArray::erase(int pos)
185 {
186         if (pos < bf_.size())
187                 erase(pos, pos + item_size(pos));
188 }
189
190
191 void MathArray::erase(int pos1, int pos2)
192 {
193         bf_.erase(bf_.begin() + pos1, bf_.begin() + pos2);
194 }
195
196
197 bool MathArray::isInset(int pos) const
198 {
199         if (pos >= size())
200                 return false;
201         return MathIsInset(bf_[pos]);
202 }
203
204
205 MathInset * MathArray::back_inset() const
206 {
207         if (!empty()) {
208                 int pos = size();
209                 prev(pos);
210                 if (isInset(pos))
211                         return GetInset(pos);
212         }
213         return 0;
214 }
215
216
217 MathScriptInset * MathArray::prevScriptInset(int pos) const
218 {
219         if (!pos)
220                 return 0;
221         prev(pos);
222
223         MathInset * inset = GetInset(pos);
224         if (inset && inset->GetType() == LM_OT_SCRIPT) 
225                 return static_cast<MathScriptInset *>(inset);
226
227         return 0;
228 }
229
230
231 void MathArray::dump2(ostream & os) const
232 {
233         for (buffer_type::const_iterator it = bf_.begin(); it != bf_.end(); ++it)
234                 os << int(*it) << ' ';
235         os << endl;
236 }
237
238
239
240 void MathArray::dump(ostream & os) const
241 {
242         for (int pos = 0; pos < size(); next(pos)) {
243                 if (isInset(pos)) 
244                         os << "<inset: " << GetInset(pos) << ">";
245                 else 
246                         os << "<" << int(bf_[pos]) << " " << int(bf_[pos+1]) << ">";
247         }
248 }
249
250
251 std::ostream & operator<<(std::ostream & os, MathArray const & ar)
252 {
253         ar.dump2(os);
254         return os;
255 }
256
257
258 void MathArray::Write(ostream & os, bool fragile) const
259 {
260         if (empty())
261                 return;
262
263         int brace = 0;
264         latexkeys const * l;
265         
266         for (int pos = 0; pos < size(); next(pos)) {
267                 if (isInset(pos)) {
268
269                         GetInset(pos)->Write(os, fragile);
270
271                 } else {
272
273                         char fcode = GetCode(pos);
274                         char c     = GetChar(pos);
275
276                         if (MathIsSymbol(fcode)) {
277                                 l = lm_get_key_by_id(c, fcode == LM_TC_BSYM ? LM_TK_BIGSYM : LM_TK_SYM);
278                                 if (l)
279                                                 os << '\\' << l->name << ' ';
280                         } else {
281                         
282                                 if (fcode >= LM_TC_RM && fcode <= LM_TC_TEXTRM) 
283                                         os << '\\' << math_font_name[fcode - LM_TC_RM] << '{';
284
285                                 // Is there a standard logical XOR?
286                                 if ((fcode == LM_TC_TEX && c != '{' && c != '}') ||
287                                                 (fcode == LM_TC_SPECIAL))
288                                         os << '\\';
289                                 else {
290                                         if (c == '{')
291                                                 ++brace;
292                                         if (c == '}')
293                                                 --brace;
294                                 }
295                                 if (c == '}' && fcode == LM_TC_TEX && brace < 0) 
296                                         lyxerr <<"Math warning: Unexpected closing brace.\n";
297                                 else           
298                                         os << char(c);
299                         }
300
301                         if (fcode >= LM_TC_RM && fcode <= LM_TC_TEXTRM)
302                                 os << '}';
303                         
304                 }
305         }
306
307         if (brace > 0)
308                 os << string(brace, '}');
309 }
310
311
312 void MathArray::WriteNormal(ostream & os) const
313 {
314         if (empty()) {
315                 os << "[par] ";
316                 return;
317         }
318
319         Write(os, true);
320 }
321