]> git.lyx.org Git - lyx.git/blob - src/dociterator.C
b8baa1a28e48b5450f3d470d8cdaa1eb3072353b
[lyx.git] / src / dociterator.C
1
2 #include "dociterator.h"
3
4 #include "debug.h"
5 #include "lyxtext.h"
6 #include "lyxrow.h"
7 #include "paragraph.h"
8
9 #include "mathed/math_data.h"
10 #include "mathed/math_inset.h"
11
12 #include <boost/assert.hpp>
13
14
15 InsetBase * DocumentIterator::nextInset()
16 {
17         if (pos() == lastpos())
18                 return 0;
19         if (inMathed()) 
20                 return nextAtom().nucleus();
21         return paragraph().isInset(pos()) ? paragraph().getInset(pos()) : 0;
22 }
23
24
25 InsetBase * DocumentIterator::prevInset()
26 {
27         if (pos() == 0)
28                 return 0;
29         if (inMathed()) 
30                 return prevAtom().nucleus();
31         return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
32 }
33
34
35 InsetBase const * DocumentIterator::prevInset() const
36 {
37         if (pos() == 0)
38                 return 0;
39         if (inMathed()) 
40                 return prevAtom().nucleus();
41         return paragraph().isInset(pos() - 1) ? paragraph().getInset(pos() - 1) : 0;
42 }
43
44
45 MathAtom const & DocumentIterator::prevAtom() const
46 {
47         BOOST_ASSERT(pos() > 0);
48         return cell()[pos() - 1];
49 }
50
51
52 MathAtom & DocumentIterator::prevAtom()
53 {
54         BOOST_ASSERT(pos() > 0);
55         return cell()[pos() - 1];
56 }
57
58
59 MathAtom const & DocumentIterator::nextAtom() const
60 {
61         BOOST_ASSERT(pos() < lastpos());
62         return cell()[pos()];
63 }
64
65
66 MathAtom & DocumentIterator::nextAtom()
67 {
68         BOOST_ASSERT(pos() < lastpos());
69         return cell()[pos()];
70 }
71
72
73 LyXText * DocumentIterator::text() const
74 {
75         return top().text();
76 }
77
78
79 Paragraph & DocumentIterator::paragraph()
80 {
81         BOOST_ASSERT(inTexted());
82         return top().paragraph();
83 }
84
85
86 Paragraph const & DocumentIterator::paragraph() const
87 {
88         BOOST_ASSERT(inTexted());
89         return top().paragraph();
90 }
91
92
93 Row & DocumentIterator::textRow()
94 {
95         return *paragraph().getRow(pos());
96 }
97
98
99 Row const & DocumentIterator::textRow() const
100 {
101         return *paragraph().getRow(pos());
102 }
103
104
105 DocumentIterator::par_type DocumentIterator::lastpar() const
106 {
107         return inMathed() ? 0 : text()->paragraphs().size() - 1;
108 }
109
110
111 DocumentIterator::pos_type DocumentIterator::lastpos() const
112 {
113         return inMathed() ? cell().size() : paragraph().size();
114 }
115
116
117 DocumentIterator::row_type DocumentIterator::crow() const
118 {
119         return paragraph().row(pos());
120 }
121
122
123 DocumentIterator::row_type DocumentIterator::lastcrow() const
124 {
125         return paragraph().rows.size();
126 }
127
128
129 DocumentIterator::idx_type DocumentIterator::lastidx() const
130 {
131         return top().lastidx();
132 }
133
134
135 size_t DocumentIterator::nargs() const
136 {
137         // assume 1x1 grid for main text
138         return top().nargs();
139 }
140
141
142 size_t DocumentIterator::ncols() const
143 {
144         // assume 1x1 grid for main text
145         return top().ncols();
146 }
147
148
149 size_t DocumentIterator::nrows() const
150 {
151         // assume 1x1 grid for main text
152         return top().nrows();
153 }
154
155
156 DocumentIterator::row_type DocumentIterator::row() const
157 {
158         return top().row();
159 }
160
161
162 DocumentIterator::col_type DocumentIterator::col() const
163 {
164         return top().col();
165 }
166
167
168 MathArray const & DocumentIterator::cell() const
169 {
170         BOOST_ASSERT(inMathed());
171         return top().cell();
172 }
173
174
175 MathArray & DocumentIterator::cell()
176 {
177         BOOST_ASSERT(inMathed());
178         return top().cell();
179 }
180
181
182 bool DocumentIterator::inMathed() const
183 {
184         return !empty() && inset().inMathed();
185 }
186
187
188 bool DocumentIterator::inTexted() const
189 {
190         return !empty() && !inset().inMathed();
191 }
192
193
194 LyXText * DocumentIterator::innerText() const
195 {
196         BOOST_ASSERT(!empty());
197         // go up until first non-0 text is hit
198         // (innermost text is 0 in mathed)
199         for (int i = size() - 1; i >= 0; --i)
200                 if (operator[](i).text())
201                         return operator[](i).text();
202         return 0;
203 }
204
205
206 InsetBase * DocumentIterator::innerInsetOfType(int code) const
207 {
208         for (int i = size() - 1; i >= 0; --i)
209                 if (operator[](i).inset_->lyxCode() == code)
210                         return operator[](i).inset_;
211         return 0;
212 }
213
214
215 void DocumentIterator::forwardPos()
216 {
217         CursorSlice & top = back();
218         //lyxerr << "XXX\n" << *this << std::endl;
219
220         // move into an inset to the right if possible
221         InsetBase * n = 0;
222         if (top.pos() != lastpos()) {
223                 // this is impossible for pos() == size()
224                 if (inMathed()) {
225                         n = (top.cell().begin() + top.pos())->nucleus();
226                 } else {
227                         if (paragraph().isInset(top.pos()))
228                                 n = paragraph().getInset(top.pos());
229                 }
230         }
231
232         if (n && n->isActive()) {
233                 //lyxerr << "... descend" << std::endl;
234                 push_back(CursorSlice(*n));
235                 return;
236         }
237
238         // otherwise move on one cell back if possible
239         if (top.pos() < lastpos()) {
240                 //lyxerr << "... next pos" << std::endl;
241                 ++top.pos();
242                 return;
243         }
244         //lyxerr << "... no next pos" << std::endl;
245
246         // otherwise move on one cell back if possible
247         if (top.par() < lastpar()) {
248                 //lyxerr << "... next par" << std::endl;
249                 ++top.par();
250                 top.pos() = 0;
251                 return;
252         }
253         //lyxerr << "... no next par" << std::endl;
254
255         // otherwise try to move on one cell if possible
256         // [stupid hack for necessary for MathScriptInset]
257         while (top.idx() < lastidx()) {
258                 //lyxerr << "... next idx" << std::endl;
259                 ++top.idx();
260                 top.par() = 0;
261                 top.pos() = 0;
262                 if (top.inset().validCell(top.idx())) {
263                         //lyxerr << "     ... ok" << std::endl;
264                         return;
265                 }
266         }
267         //lyxerr << "... no next idx" << std::endl;
268
269         // otherwise leave inset an jump over inset as a whole
270         pop_back();
271         // 'top' is invalid now...
272         if (size())
273                 ++back().pos_;
274         //else
275         //      lyxerr << "... no slice left" << std::endl;
276 }
277
278
279 void DocumentIterator::forwardPar()
280 {
281         CursorSlice & top = back();
282         lyxerr << "XXX " << *this << std::endl;
283
284         // move into an inset to the right if possible
285         InsetBase * n = 0;
286         if (top.pos() != lastpos()) {
287                 // this is impossible for pos() == size()
288                 if (inMathed()) {
289                         n = (top.cell().begin() + top.pos())->nucleus();
290                 } else {
291                         if (paragraph().isInset(top.pos()))
292                                 n = paragraph().getInset(top.pos());
293                 }
294         }
295
296         if (n && n->isActive()) {
297                 lyxerr << "... descend" << std::endl;
298                 push_back(CursorSlice(*n));
299                 return;
300         }
301
302         // otherwise move on one cell back if possible
303         if (top.pos() < lastpos()) {
304                 lyxerr << "... next pos" << std::endl;
305                 ++top.pos();
306                 return;
307         }
308
309         // otherwise move on one cell back if possible
310         if (top.par() < lastpar()) {
311                 lyxerr << "... next par" << std::endl;
312                 ++top.par();
313                 top.pos() = 0;
314                 return;
315         }
316
317         // otherwise try to move on one cell if possible
318         // [stupid hack for necessary for MathScriptInset]
319         while (top.idx() < top.lastidx()) {
320                 lyxerr << "... next idx" 
321                         << " was: " << top.idx() << " max: " << top.lastidx() << std::endl;
322                 ++top.idx();
323                 top.par() = 0;
324                 top.pos() = 0;
325                 if (top.inset().validCell(top.idx())) {
326                         lyxerr << "     ... ok" << std::endl;
327                         return;
328                 }
329         }
330
331         // otherwise leave inset an jump over inset as a whole
332         pop_back();
333         // 'top' is invalid now...
334         if (size())
335                 ++back().pos_;
336 }
337
338
339 DocumentIterator insetBegin(InsetBase & inset)
340 {
341         DocumentIterator it;
342         it.push_back(CursorSlice(inset));
343         return it;
344 }
345
346
347 DocumentIterator insetEnd()
348 {
349         return DocumentIterator();
350 }
351
352
353 std::ostream & operator<<(std::ostream & os, DocumentIterator const & dit)
354 {
355         for (size_t i = 0, n = dit.size(); i != n; ++i)
356                 os << " " << dit.operator[](i) << "\n";
357         return os;
358 }
359
360
361
362 ///////////////////////////////////////////////////////
363
364 StableDocumentIterator::StableDocumentIterator(const DocumentIterator & dit)
365 {
366         data_ = dit;
367         for (size_t i = 0, n = data_.size(); i != n; ++i)
368                 data_[i].inset_ = 0;
369 }
370
371
372 DocumentIterator
373 StableDocumentIterator::asDocumentIterator(InsetBase * inset) const
374 {
375         // this function re-creates the cache of inset pointers
376         //lyxerr << "converting:\n" << *this << std::endl;
377         DocumentIterator dit;
378         for (size_t i = 0, n = data_.size(); i != n; ++i) {
379                 dit.push_back(data_[i]);
380                 dit.back().inset_ = inset;
381                 if (i + 1 != n)
382                         inset = dit.nextInset();
383         }
384         //lyxerr << "convert:\n" << *this << " to:\n" << dit << std::endl;
385         return dit;
386 }
387
388
389 std::ostream & operator<<(std::ostream & os, StableDocumentIterator const & dit)
390 {
391         for (size_t i = 0, n = dit.data_.size(); i != n; ++i)
392                 os << " " << dit.data_[i] << "\n";
393         return os;
394 }
395