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