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