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