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/InsetMathMacro.h"
27
28 #include "support/ExceptionMessage.h"
29 #include "support/gettext.h"
30 #include "support/lassert.h"
31
32 #include <ostream>
33
34 using namespace std;
35
36 namespace lyx {
37
38
CursorSlice()39 CursorSlice::CursorSlice()
40 : inset_(0), idx_(0), pit_(0), pos_(0)
41 {}
42
43
CursorSlice(Inset & p)44 CursorSlice::CursorSlice(Inset & p)
45 : inset_(&p), idx_(0), pit_(0), pos_(0)
46 {
47 LBUFERR(inset_);
48 }
49
50
cell() const51 MathData & CursorSlice::cell() const
52 {
53 return inset_->asInsetMath()->cell(idx_);
54 }
55
56
paragraph() const57 Paragraph & CursorSlice::paragraph() const
58 {
59 return text()->getPar(pit_);
60 }
61
62
lastpos() const63 pos_type CursorSlice::lastpos() const
64 {
65 LBUFERR(inset_);
66 InsetMath const * math = inset_->asInsetMath();
67 bool paramless_macro = math && math->asMacro() && !math->asMacro()->nargs();
68 return math ? (paramless_macro ? 0 : cell().size())
69 : (text()->empty() ? 0 : paragraph().size());
70 }
71
72
lastpit() const73 pit_type CursorSlice::lastpit() const
74 {
75 if (inset_->inMathed())
76 return 0;
77 return text()->paragraphs().size() - 1;
78 }
79
80
row() const81 CursorSlice::row_type CursorSlice::row() const
82 {
83 LASSERT(inset_, return 0);
84 return inset_->row(idx_);
85 }
86
87
col() const88 CursorSlice::col_type CursorSlice::col() const
89 {
90 LASSERT(inset_, return 0);
91 return inset_->col(idx_);
92 }
93
94
setPitPos(pit_type pit,pos_type pos)95 void CursorSlice::setPitPos(pit_type pit, pos_type pos)
96 {
97 LASSERT(pit != int(text()->paragraphs().size()), return);
98 pit_ = pit;
99 pos_ = pos;
100
101 // Now some strict checking. None of these should happen, but
102 // we're scaredy-cats
103 if (pos < 0) {
104 LYXERR0("Don't like -1!");
105 LATTEST(false);
106 }
107
108 if (pos > paragraph().size()) {
109 LYXERR0("Don't like 1, pos: " << pos
110 << " size: " << paragraph().size()
111 << " par: " << pit);
112 LATTEST(false);
113 }
114 }
115
116
forwardPos()117 void CursorSlice::forwardPos()
118 {
119 // move on one position if possible
120 if (pos_ < lastpos()) {
121 //lyxerr << "... next pos" << endl;
122 ++pos_;
123 return;
124 }
125
126 // otherwise move on one paragraph if possible
127 if (pit_ < lastpit()) {
128 //lyxerr << "... next par" << endl;
129 ++pit_;
130 pos_ = 0;
131 return;
132 }
133
134 // otherwise move on one cell
135 //lyxerr << "... next idx" << endl;
136
137 LASSERT(idx_ < nargs(), return);
138
139 ++idx_;
140 pit_ = 0;
141 pos_ = 0;
142 }
143
144
forwardIdx()145 void CursorSlice::forwardIdx()
146 {
147 LASSERT(idx_ < nargs(), return);
148
149 ++idx_;
150 pit_ = 0;
151 pos_ = 0;
152 }
153
154
backwardPos()155 void CursorSlice::backwardPos()
156 {
157 if (pos_ != 0) {
158 --pos_;
159 return;
160 }
161
162 if (pit_ != 0) {
163 --pit_;
164 pos_ = lastpos();
165 return;
166 }
167
168 if (idx_ != 0) {
169 --idx_;
170 pit_ = lastpit();
171 pos_ = lastpos();
172 return;
173 }
174
175 LATTEST(false);
176 }
177
178
at_cell_end() const179 bool CursorSlice::at_cell_end() const
180 {
181 return pit_ == lastpit() && pos_ == lastpos();
182 }
183
184
at_cell_begin() const185 bool CursorSlice::at_cell_begin() const
186 {
187 return pit_ == 0 && pos_ == 0;
188 }
189
190
at_end() const191 bool CursorSlice::at_end() const
192 {
193 return idx_ == lastidx() && at_cell_end();
194 }
195
196
at_begin() const197 bool CursorSlice::at_begin() const
198 {
199 return idx_ == 0 && at_cell_begin();
200 }
201
202
operator ==(CursorSlice const & p,CursorSlice const & q)203 bool operator==(CursorSlice const & p, CursorSlice const & q)
204 {
205 return p.inset_ == q.inset_
206 && p.idx_ == q.idx_
207 && p.pit_ == q.pit_
208 && p.pos_ == q.pos_;
209 }
210
211
operator !=(CursorSlice const & p,CursorSlice const & q)212 bool operator!=(CursorSlice const & p, CursorSlice const & q)
213 {
214 return p.inset_ != q.inset_
215 || p.idx_ != q.idx_
216 || p.pit_ != q.pit_
217 || p.pos_ != q.pos_;
218 }
219
220
operator <(CursorSlice const & p,CursorSlice const & q)221 bool operator<(CursorSlice const & p, CursorSlice const & q)
222 {
223 if (p.inset_ != q.inset_) {
224 LYXERR0("can't compare cursor and anchor in different insets\n"
225 << "p: " << p << '\n' << "q: " << q);
226 // It should be safe to continue, just registering the error.
227 LASSERT(false, return false);
228 }
229 if (p.idx_ != q.idx_)
230 return p.idx_ < q.idx_;
231 if (p.pit_ != q.pit_)
232 return p.pit_ < q.pit_;
233 return p.pos_ < q.pos_;
234 }
235
236
operator >(CursorSlice const & p,CursorSlice const & q)237 bool operator>(CursorSlice const & p, CursorSlice const & q)
238 {
239 return q < p;
240 }
241
242
operator <=(CursorSlice const & p,CursorSlice const & q)243 bool operator<=(CursorSlice const & p, CursorSlice const & q)
244 {
245 return !(q < p);
246 }
247
248
operator <<(ostream & os,CursorSlice const & item)249 ostream & operator<<(ostream & os, CursorSlice const & item)
250 {
251 return os
252 << "inset: " << (void *)item.inset_
253 // << " text: " << item.text()
254 << " idx: " << item.idx_
255 << " par: " << item.pit_
256 << " pos: " << item.pos_
257 // << " x: " << item.inset_->x()
258 // << " y: " << item.inset_->y()
259 ;
260 }
261
262
263 } // namespace lyx
264