Kate
katesmartcursor.cpp
Go to the documentation of this file.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 KTextEditor::Cursor old = *this;
00145
00146
00147 if (m_lastPositionNeeded)
00148 m_lastPosition = *this;
00149
00150
00151 bool haveToChangeGroups = !m_smartGroup->containsLine(pos.line());
00152 if (haveToChangeGroups) {
00153 m_smartGroup->leaving(this);
00154 m_smartGroup = kateDocument()->smartManager()->groupForLine(pos.line());
00155 }
00156
00157
00158 m_line = pos.line() - m_smartGroup->newStartLine();
00159 m_column = pos.column();
00160
00161
00162 if (haveToChangeGroups) {
00163 m_smartGroup->joined(this);
00164 }
00165
00166
00167 if (!m_lastPositionNeeded)
00168 m_lastPosition = *this;
00169
00170
00171 if (!internal)
00172
00173 cursorChangedDirectly(old);
00174
00175 #ifdef DEBUG_KATESMARTCURSOR
00176 kDebug() << this << "Cursor moved from" << old << "to" << *this;
00177 #endif
00178 }
00179
00180 KTextEditor::SmartCursorNotifier* KateSmartCursor::notifier( )
00181 {
00182 if (!m_notifier) {
00183 m_notifier = new KateSmartCursorNotifier();
00184 checkFeedback();
00185 }
00186 return m_notifier;
00187 }
00188
00189 void KateSmartCursor::deleteNotifier( )
00190 {
00191 delete m_notifier;
00192 m_notifier = 0L;
00193 checkFeedback();
00194 }
00195
00196 void KateSmartCursor::setWatcher( KTextEditor::SmartCursorWatcher * watcher )
00197 {
00198 m_watcher = watcher;
00199 checkFeedback();
00200 }
00201
00202 bool KateSmartCursor::translate( const KateEditInfo & edit )
00203 {
00204 #ifdef DEBUG_KATESMARTCURSOR
00205 kDebug() << this << "Translating cursor" << *this << "from " << edit.oldRange() << "to" << edit.newRange() << edit.editSource() << &edit;
00206 #endif
00207
00208 if (m_bypassTranslation) {
00209 if (m_bypassTranslation == &edit) {
00210
00211 m_bypassTranslation = 0;
00212 return true;
00213 }
00214
00215 m_bypassTranslation = 0;
00216 }
00217
00218
00219 if (*this < edit.start())
00220 return false;
00221
00222
00223 KTextEditor::Cursor newPos;
00224
00225
00226 if (edit.oldRange().overlapsLine(line())) {
00227
00228 if (*this == edit.start()) {
00229
00230 if (insertBehavior() == KTextEditor::SmartCursor::StayOnInsert)
00231 return false;
00232 }
00233
00234 if (edit.oldRange().contains(*this)) {
00235 if (insertBehavior() == KTextEditor::SmartCursor::MoveOnInsert)
00236 newPos = edit.newRange().end();
00237 else
00238 newPos = edit.start();
00239
00240 } else {
00241 newPos = *this + edit.translate();
00242 }
00243
00244 } else {
00245
00246 newPos.setPosition(line() + edit.translate().line(), column());
00247 }
00248
00249 if (newPos != *this) {
00250
00251
00252 if (KTextEditor::SmartRange* range = smartRange()) {
00253 if (&(range->smartStart()) == this) {
00254 if (*this == edit.start()) {
00255 if (range->insertBehavior() == KTextEditor::SmartRange::DoNotExpand) {
00256 if (range->end() == *this) {
00257 KateSmartCursor* end = static_cast<KateSmartCursor*>(&(range->smartEnd()));
00258 end->setPositionInternal(newPos);
00259
00260 end->m_bypassTranslation = &edit;
00261 }
00262 }
00263 }
00264 }
00265 }
00266
00267 setPositionInternal(newPos);
00268 return true;
00269 }
00270
00271 return false;
00272 }
00273
00274 bool KateSmartCursor::cursorMoved( ) const
00275 {
00276 bool ret = m_oldGroupLineStart != m_smartGroup->startLine();
00277 m_oldGroupLineStart = m_smartGroup->startLine();
00278 return ret;
00279 }
00280
00281 void KateSmartCursor::setLineInternal( int newLine, bool internal )
00282 {
00283 setPositionInternal(KTextEditor::Cursor(newLine, column()), internal);
00284 }
00285
00286 void KateSmartCursor::translated(const KateEditInfo & edit)
00287 {
00288 if (*this < edit.start()) {
00289 if (!range() || !static_cast<KateSmartRange*>(range())->feedbackEnabled())
00290 m_lastPosition = *this;
00291 return;
00292 }
00293
00294
00295 if (m_lastPosition != *this) {
00296
00297 if (m_notifier)
00298 emit m_notifier->positionChanged(this);
00299 if (m_watcher)
00300 m_watcher->positionChanged(this);
00301 }
00302
00303 if (!edit.oldRange().isEmpty() && edit.start() <= m_lastPosition && edit.oldRange().end() >= m_lastPosition) {
00304 if (edit.start() == m_lastPosition) {
00305
00306 if (m_notifier)
00307 emit m_notifier->characterDeleted(this, false);
00308 if (m_watcher)
00309 m_watcher->characterDeleted(this, false);
00310
00311 } else if (edit.oldRange().end() == m_lastPosition) {
00312
00313 if (m_notifier)
00314 emit m_notifier->characterDeleted(this, true);
00315 if (m_watcher)
00316 m_watcher->characterDeleted(this, true);
00317
00318 } else {
00319
00320 if (m_notifier)
00321 emit m_notifier->positionDeleted(this);
00322 if (m_watcher)
00323 m_watcher->positionDeleted(this);
00324 }
00325 }
00326
00327 if (!edit.newRange().isEmpty()) {
00328 if (*this == edit.newRange().start()) {
00329
00330 if (m_notifier)
00331 emit m_notifier->characterInserted(this, false);
00332 if (m_watcher)
00333 m_watcher->characterInserted(this, false);
00334
00335 } else if (*this == edit.newRange().end()) {
00336
00337 if (m_notifier)
00338 emit m_notifier->characterInserted(this, true);
00339 if (m_watcher)
00340 m_watcher->characterInserted(this, true);
00341 }
00342 }
00343
00344 if (!range() || !static_cast<KateSmartRange*>(range())->feedbackEnabled())
00345 m_lastPosition = *this;
00346 }
00347
00348 void KateSmartCursor::shifted( )
00349 {
00350 Q_ASSERT(m_lastPosition != *this);
00351
00352
00353 if (m_notifier)
00354 emit m_notifier->positionChanged(this);
00355 if (m_watcher)
00356 m_watcher->positionChanged(this);
00357
00358 if (!range() || !static_cast<KateSmartRange*>(range())->feedbackEnabled())
00359 m_lastPosition = *this;
00360 }
00361
00362 void KateSmartCursor::migrate( KateSmartGroup * newGroup )
00363 {
00364 int lineNum = line();
00365 m_smartGroup = newGroup;
00366 m_line = lineNum - m_smartGroup->startLine();
00367 }
00368
00369 void KateSmartCursor::setPosition( const KTextEditor::Cursor & pos )
00370 {
00371 if (pos.line() > kateDocument()->lastLine()) {
00372 kWarning() << "Attempted to set cursor position " << pos << " past end of document " << document()->documentRange();
00373 setPositionInternal(invalid(), false);
00374 return;
00375 }
00376
00377 setPositionInternal(pos, false);
00378 }
00379
00380 void KateSmartCursor::resetLastPosition( )
00381 {
00382 m_lastPosition = *this;
00383 }
00384
00385 bool KateSmartCursor::hasNotifier( ) const
00386 {
00387 return m_notifier;
00388 }
00389
00390 KTextEditor::SmartCursorWatcher * KateSmartCursor::watcher( ) const
00391 {
00392 return m_watcher;
00393 }
00394
00395 void KateSmartCursor::unbindFromRange( )
00396 {
00397 setRange(0L);
00398 }
00399
00400 void KateSmartCursor::setInternal( )
00401 {
00402 m_isInternal = true;
00403 }
00404
00405