]> git.lyx.org Git - lyx.git/blob - src/CursorSlice.cpp
Fix bug #8105: Crash when deleting math macro from the inside
[lyx.git] / src / CursorSlice.cpp
1 /**
2  * \file CursorSlice.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Lars Gullik Bjønnes
7  * \author Matthias Ettrich
8  * \author André Pönitz
9  * \author Jürgen Vigna
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "CursorSlice.h"
17
18 #include "Text.h"
19 #include "Paragraph.h"
20
21 #include "support/debug.h"
22
23 #include "insets/Inset.h"
24
25 #include "mathed/InsetMath.h"
26 #include "mathed/MathMacro.h"
27
28 #include "support/lassert.h"
29
30 #include <ostream>
31
32 using namespace std;
33
34 namespace lyx {
35
36
37 CursorSlice::CursorSlice()
38         : inset_(0), idx_(0), pit_(0), pos_(0)
39 {}
40
41
42 CursorSlice::CursorSlice(Inset & p)
43         : inset_(&p), idx_(0), pit_(0), pos_(0)
44 {
45         LASSERT(inset_, /**/);
46 }
47
48
49 MathData & CursorSlice::cell() const
50 {
51         return inset_->asInsetMath()->cell(idx_);
52 }
53
54
55 Paragraph & CursorSlice::paragraph() const
56 {
57         return text()->getPar(pit_);
58 }
59
60
61 pos_type CursorSlice::lastpos() const
62 {
63         LASSERT(inset_, /**/);
64         InsetMath const * math = inset_->asInsetMath();
65         bool paramless_macro = math && math->asMacro() && !math->asMacro()->nargs();
66         return math ? (paramless_macro ? 0 : cell().size()) 
67                     : (text()->empty() ? 0 : paragraph().size());
68 }
69
70
71 pit_type CursorSlice::lastpit() const
72 {
73         if (inset_->inMathed())
74                 return 0;
75         return text()->paragraphs().size() - 1;
76 }
77
78
79 CursorSlice::row_type CursorSlice::row() const
80 {
81         LASSERT(asInsetMath(), /**/);
82         return asInsetMath()->row(idx_);
83 }
84
85
86 CursorSlice::col_type CursorSlice::col() const
87 {
88         LASSERT(asInsetMath(), /**/);
89         return asInsetMath()->col(idx_);
90 }
91
92
93 void CursorSlice::forwardPos()
94 {
95         //  move on one position if possible
96         if (pos_ < lastpos()) {
97                 //lyxerr << "... next pos" << endl;
98                 ++pos_;
99                 return;
100         }
101
102         // otherwise move on one paragraph if possible
103         if (pit_ < lastpit()) {
104                 //lyxerr << "... next par" << endl;
105                 ++pit_;
106                 pos_ = 0;
107                 return;
108         }
109
110         // otherwise move on one cell
111         //lyxerr << "... next idx" << endl;
112
113         LASSERT(idx_ < nargs(), /**/);
114
115         ++idx_;
116         pit_ = 0;
117         pos_ = 0;
118 }
119
120
121 void CursorSlice::forwardIdx()
122 {
123         LASSERT(idx_ < nargs(), /**/);
124
125         ++idx_;
126         pit_ = 0;
127         pos_ = 0;
128 }
129
130
131 void CursorSlice::backwardPos()
132 {
133         if (pos_ != 0) {
134                 --pos_;
135                 return;
136         }
137
138         if (pit_ != 0) {
139                 --pit_;
140                 pos_ = lastpos();
141                 return;
142         }
143
144         if (idx_ != 0) {
145                 --idx_;
146                 pit_ = lastpit();
147                 pos_ = lastpos();
148                 return;
149         }
150
151         LASSERT(false, /**/);
152 }
153
154
155 bool CursorSlice::at_end() const 
156 {
157         return idx_ == lastidx() && pit_ == lastpit() && pos_ == lastpos();
158 }
159
160
161 bool CursorSlice::at_begin() const
162 {
163         return idx_ == 0 && pit_ == 0 && pos_ == 0;
164 }
165
166
167 bool operator==(CursorSlice const & p, CursorSlice const & q)
168 {
169         return p.inset_ == q.inset_
170                && p.idx_ == q.idx_
171                && p.pit_ == q.pit_
172                && p.pos_ == q.pos_;
173 }
174
175
176 bool operator!=(CursorSlice const & p, CursorSlice const & q)
177 {
178         return p.inset_ != q.inset_
179                || p.idx_ != q.idx_
180                || p.pit_ != q.pit_
181                || p.pos_ != q.pos_;
182 }
183
184
185 bool operator<(CursorSlice const & p, CursorSlice const & q)
186 {
187         if (p.inset_ != q.inset_) {
188                 LYXERR0("can't compare cursor and anchor in different insets\n"
189                        << "p: " << p << '\n' << "q: " << q);
190                 LASSERT(false, /**/);
191         }
192         if (p.idx_ != q.idx_)
193                 return p.idx_ < q.idx_;
194         if (p.pit_ != q.pit_)
195                 return p.pit_ < q.pit_;
196         return p.pos_ < q.pos_;
197 }
198
199
200 bool operator>(CursorSlice const & p, CursorSlice const & q)
201 {
202         return q < p;
203 }
204
205
206 bool operator<=(CursorSlice const & p, CursorSlice const & q)
207 {
208         return !(q < p);
209 }
210
211
212 ostream & operator<<(ostream & os, CursorSlice const & item)
213 {
214         return os
215            << "inset: " << (void *)item.inset_
216 //         << " text: " << item.text()
217            << " idx: " << item.idx_
218            << " par: " << item.pit_
219            << " pos: " << item.pos_
220 //         << " x: " << item.inset_->x()
221 //         << " y: " << item.inset_->y()
222 ;
223 }
224
225
226 } // namespace lyx