00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "katesmartcursor.h"
00020
00021 #include "katedocument.h"
00022 #include "katesmartmanager.h"
00023 #include "katesmartcursornotifier.h"
00024 #include "katesmartrange.h"
00025
00026 #include <kdebug.h>
00027
00028
00029
00030 KateSmartCursor::KateSmartCursor(const KTextEditor::Cursor& position, KTextEditor::Document* doc, KTextEditor::SmartCursor::InsertBehavior insertBehavior)
00031 : KTextEditor::SmartCursor(position, doc, insertBehavior)
00032 , m_oldGroupLineStart(-1)
00033 , m_lastPosition(position)
00034 , m_feedbackEnabled(false)
00035 , m_isInternal(false)
00036 , m_lastPositionNeeded(false)
00037 , m_bypassTranslation(0)
00038 , m_notifier(0L)
00039 , m_watcher(0L)
00040 {
00041 if (position.line() > kateDocument()->lastLine()) {
00042 kWarning() << "Attempted to set cursor position " << position << " past end of document " << doc->documentRange();
00043 m_line = -1;
00044 m_column = -1;
00045 }
00046
00047
00048 m_smartGroup = kateDocument()->smartManager()->groupForLine(m_line);
00049 m_line = m_line - m_smartGroup->startLine();
00050 m_smartGroup->joined(this);
00051
00052 #ifdef DEBUG_KATESMARTCURSOR
00053 kDebug() << "Cursor created at " << *this;
00054 #endif
00055 }
00056
00057 KateSmartCursor::KateSmartCursor( KTextEditor::Document * doc, KTextEditor::SmartCursor::InsertBehavior insertBehavior )
00058 : KTextEditor::SmartCursor(KTextEditor::Cursor(), doc, insertBehavior)
00059 , m_oldGroupLineStart(-1)
00060 , m_feedbackEnabled(false)
00061 , m_isInternal(false)
00062 , m_lastPositionNeeded(false)
00063 , m_bypassTranslation(0)
00064 , m_notifier(0L)
00065 , m_watcher(0L)
00066 {
00067
00068 m_smartGroup = kateDocument()->smartManager()->groupForLine(m_line);
00069 m_line = m_line - m_smartGroup->startLine();
00070 m_smartGroup->joined(this);
00071
00072 #ifdef DEBUG_KATESMARTCURSOR
00073 kDebug() << this << "Cursor created at " << *this;
00074 #endif
00075 }
00076
00077 KateSmartCursor::~KateSmartCursor()
00078 {
00079 if (m_notifier) {
00080 emit m_notifier->deleted(this);
00081 delete m_notifier;
00082 }
00083
00084 if (m_watcher)
00085 m_watcher->deleted(this);
00086
00087 if (!kateDocument()->smartManager()->isClearing())
00088 m_smartGroup->leaving(this);
00089 }
00090
00091 KateSmartCursor::operator QString()
00092 {
00093 return QString("[%1,%1]").arg(line()).arg(column());
00094 }
00095
00096 KateDocument* KateSmartCursor::kateDocument() const
00097 {
00098 return static_cast<KateDocument*>(document());
00099 }
00100
00101 bool KateSmartCursor::isValid( ) const
00102 {
00103 return line() >= 0 && column() >= 0 && line() <= kateDocument()->lastLine() && column() <= kateDocument()->lineLength(line());
00104 }
00105
00106 bool KateSmartCursor::isValid(const Cursor& position) const
00107 {
00108 return position.line() >= 0 && position.line() <= kateDocument()->lastLine() && position.column() >= 0 && position.column() <= kateDocument()->lineLength(position.line());
00109 }
00110
00111 bool KateSmartCursor::atEndOfLine( ) const
00112 {
00113 return line() >= 0 && line() <= kateDocument()->lastLine() && column() >= kateDocument()->lineLength(line());
00114 }
00115
00116 void KateSmartCursor::checkFeedback()
00117 {
00118 bool feedbackNeeded = m_watcher || m_notifier;
00119
00120 m_lastPositionNeeded = feedbackNeeded || (range() && static_cast<KateSmartRange*>(range())->feedbackEnabled());
00121
00122 if (m_feedbackEnabled != feedbackNeeded) {
00123 m_smartGroup->changeCursorFeedback(this);
00124 m_feedbackEnabled = feedbackNeeded;
00125 }
00126 }
00127
00128 int KateSmartCursor::line( ) const
00129 {
00130 return m_smartGroup->startLine() + m_line;
00131 }
00132
00133 void KateSmartCursor::setLine( int _line )
00134 {
00135 setPositionInternal(KTextEditor::Cursor(_line, m_column), false);
00136 }
00137
00138 void KateSmartCursor::setPositionInternal( const KTextEditor::Cursor & pos, bool internal )
00139 {
00140
00141 if (*this == pos)
00142 return;
00143
00144
00145 KTextEditor::Cursor oldOther;
00146
00147 if(m_range) {
00148 KTextEditor::SmartRange* smartRange = m_range->toSmartRange();
00149
00150 if(!internal && smartRange) {
00151 KateSmartCursor& start = dynamic_cast<KateSmartCursor&>(smartRange->smartStart());
00152 KateSmartCursor& end = dynamic_cast<KateSmartCursor&>(smartRange->smartEnd());
00153
00154
00155
00156 if(this == &start) {
00157 oldOther = end;
00158 if(pos > end)
00159
00160 end.setPositionInternal(pos, true);
00161 }else{
00162 Q_ASSERT(this == &end);
00163 oldOther = start;
00164 if(pos < start)
00165
00166 start.setPositionInternal(pos, true);
00167 }
00168 }
00169 }
00170
00171 KTextEditor::Cursor old = *this;
00172
00173
00174 if (m_lastPositionNeeded)
00175 m_lastPosition = *this;
00176
00177
00178 bool haveToChangeGroups = !m_smartGroup->containsLine(pos.line());
00179 if (haveToChangeGroups) {
00180 m_smartGroup->leaving(this);
00181 m_smartGroup = kateDocument()->smartManager()->groupForLine(pos.line());
00182 }
00183
00184
00185 m_line = pos.line() - m_smartGroup->newStartLine();
00186 m_column = pos.column();
00187
00188
00189 if (haveToChangeGroups) {
00190 m_smartGroup->joined(this);
00191 }
00192
00193
00194 if (!m_lastPositionNeeded)
00195 m_lastPosition = *this;
00196
00197
00198 if (!internal) {
00199
00200
00201
00202 if (m_range) {
00203 if (this == &m_range->start())
00204 static_cast<KateSmartRange*>(m_range)->rangeChanged(0, KTextEditor::Range(old, oldOther));
00205 else
00206 static_cast<KateSmartRange*>(m_range)->rangeChanged(0, KTextEditor::Range(oldOther, old));
00207 }
00208 }
00209
00210 #ifdef DEBUG_KATESMARTCURSOR
00211 kDebug() << this << "Cursor moved from" << old << "to" << *this;
00212 #endif
00213 }
00214
00215 KTextEditor::SmartCursorNotifier* KateSmartCursor::notifier( )
00216 {
00217 if (!m_notifier) {
00218 m_notifier = new KateSmartCursorNotifier();
00219 checkFeedback();
00220 }
00221 return m_notifier;
00222 }
00223
00224 void KateSmartCursor::deleteNotifier( )
00225 {
00226 delete m_notifier;
00227 m_notifier = 0L;
00228 checkFeedback();
00229 }
00230
00231 void KateSmartCursor::setWatcher( KTextEditor::SmartCursorWatcher * watcher )
00232 {
00233 m_watcher = watcher;
00234 checkFeedback();
00235 }
00236
00237 bool KateSmartCursor::translate( const KateEditInfo & edit )
00238 {
00239 #ifdef DEBUG_KATESMARTCURSOR
00240 kDebug() << this << "Translating cursor" << *this << "from " << edit.oldRange() << "to" << edit.newRange() << edit.editSource() << &edit;
00241 #endif
00242
00243 if (m_bypassTranslation) {
00244 if (m_bypassTranslation == &edit) {
00245
00246 m_bypassTranslation = 0;
00247 return true;
00248 }
00249
00250 m_bypassTranslation = 0;
00251 }
00252
00253
00254 if (*this < edit.start())
00255 return false;
00256
00257
00258 KTextEditor::Cursor newPos;
00259
00260
00261 if (edit.oldRange().overlapsLine(line())) {
00262
00263 if (*this == edit.start()) {
00264
00265 if (insertBehavior() == KTextEditor::SmartCursor::StayOnInsert)
00266 return false;
00267 }
00268
00269 if (edit.oldRange().contains(*this)) {
00270 if (insertBehavior() == KTextEditor::SmartCursor::MoveOnInsert)
00271 newPos = edit.newRange().end();
00272 else
00273 newPos = edit.start();
00274
00275 } else {
00276 newPos = *this + edit.translate();
00277 }
00278
00279 } else {
00280
00281 newPos.setPosition(line() + edit.translate().line(), column());
00282 }
00283
00284 if (newPos != *this) {
00285
00286
00287 if (KTextEditor::SmartRange* range = smartRange()) {
00288
00289 if (&(range->smartStart()) == this) {
00290 if (*this == edit.start()) {
00291 if (range->insertBehavior() == KTextEditor::SmartRange::DoNotExpand) {
00292 if (range->end() == *this) {
00293 KateSmartCursor* end = static_cast<KateSmartCursor*>(&(range->smartEnd()));
00294 end->setPositionInternal(newPos);
00295
00296 end->m_bypassTranslation = &edit;
00297 }
00298 }
00299 }
00300 }else{
00301 }
00302 }
00303
00304 setPositionInternal(newPos);
00305 return true;
00306 }
00307
00308 return false;
00309 }
00310
00311 bool KateSmartCursor::cursorMoved( ) const
00312 {
00313 bool ret = m_oldGroupLineStart != m_smartGroup->startLine();
00314 m_oldGroupLineStart = m_smartGroup->startLine();
00315 return ret;
00316 }
00317
00318 void KateSmartCursor::setLineInternal( int newLine, bool internal )
00319 {
00320 setPositionInternal(KTextEditor::Cursor(newLine, column()), internal);
00321 }
00322
00323 void KateSmartCursor::translated(const KateEditInfo & edit)
00324 {
00325 if (*this < edit.start()) {
00326 if (!range() || !static_cast<KateSmartRange*>(range())->feedbackEnabled())
00327 m_lastPosition = *this;
00328 return;
00329 }
00330
00331
00332 if (m_lastPosition != *this) {
00333
00334 if (m_notifier)
00335 emit m_notifier->positionChanged(this);
00336 if (m_watcher)
00337 m_watcher->positionChanged(this);
00338 }
00339
00340 if (!edit.oldRange().isEmpty() && edit.start() <= m_lastPosition && edit.oldRange().end() >= m_lastPosition) {
00341 if (edit.start() == m_lastPosition) {
00342
00343 if (m_notifier)
00344 emit m_notifier->characterDeleted(this, false);
00345 if (m_watcher)
00346 m_watcher->characterDeleted(this, false);
00347
00348 } else if (edit.oldRange().end() == m_lastPosition) {
00349
00350 if (m_notifier)
00351 emit m_notifier->characterDeleted(this, true);
00352 if (m_watcher)
00353 m_watcher->characterDeleted(this, true);
00354
00355 } else {
00356
00357 if (m_notifier)
00358 emit m_notifier->positionDeleted(this);
00359 if (m_watcher)
00360 m_watcher->positionDeleted(this);
00361 }
00362 }
00363
00364 if (!edit.newRange().isEmpty()) {
00365 if (*this == edit.newRange().start()) {
00366
00367 if (m_notifier)
00368 emit m_notifier->characterInserted(this, false);
00369 if (m_watcher)
00370 m_watcher->characterInserted(this, false);
00371
00372 } else if (*this == edit.newRange().end()) {
00373
00374 if (m_notifier)
00375 emit m_notifier->characterInserted(this, true);
00376 if (m_watcher)
00377 m_watcher->characterInserted(this, true);
00378 }
00379 }
00380
00381 if (!range() || !static_cast<KateSmartRange*>(range())->feedbackEnabled())
00382 m_lastPosition = *this;
00383 }
00384
00385 void KateSmartCursor::shifted( )
00386 {
00387 Q_ASSERT(m_lastPosition != *this);
00388
00389
00390 if (m_notifier)
00391 emit m_notifier->positionChanged(this);
00392 if (m_watcher)
00393 m_watcher->positionChanged(this);
00394
00395 if (!range() || !static_cast<KateSmartRange*>(range())->feedbackEnabled())
00396 m_lastPosition = *this;
00397 }
00398
00399 void KateSmartCursor::migrate( KateSmartGroup * newGroup )
00400 {
00401 int lineNum = line();
00402 m_smartGroup = newGroup;
00403 m_line = lineNum - m_smartGroup->startLine();
00404 }
00405
00406 void KateSmartCursor::setPosition( const KTextEditor::Cursor & pos )
00407 {
00408 if (pos.line() > kateDocument()->lastLine()) {
00409 kWarning() << "Attempted to set cursor position " << pos << " past end of document " << document()->documentRange();
00410 setPositionInternal(invalid(), false);
00411 return;
00412 }
00413
00414 setPositionInternal(pos, false);
00415 }
00416
00417 void KateSmartCursor::resetLastPosition( )
00418 {
00419 m_lastPosition = *this;
00420 }
00421
00422 bool KateSmartCursor::hasNotifier( ) const
00423 {
00424 return m_notifier;
00425 }
00426
00427 KTextEditor::SmartCursorWatcher * KateSmartCursor::watcher( ) const
00428 {
00429 return m_watcher;
00430 }
00431
00432 void KateSmartCursor::unbindFromRange( )
00433 {
00434 setRange(0L);
00435 }
00436
00437 void KateSmartCursor::setInternal( )
00438 {
00439 m_isInternal = true;
00440 }
00441
00442