00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "katesmartmanager.h"
00019
00020 #include "katedocument.h"
00021 #include "kateedit.h"
00022 #include "katesmartcursor.h"
00023 #include "katesmartrange.h"
00024
00025 #include <QThread>
00026 #include <QMutexLocker>
00027
00028 #include <kdebug.h>
00029
00030
00031
00032
00033
00034
00035 static const int s_defaultGroupSize = 40;
00036 static const int s_minimumGroupSize = 20;
00037 static const int s_maximumGroupSize = 60;
00038
00039 using namespace KTextEditor;
00040
00041 static void translate(KateEditInfo* edit, Cursor& ret, SmartCursor::InsertBehavior insertBehavior)
00042 {
00043
00044
00045 if (ret < edit->start())
00046 return;
00047
00048
00049 if (edit->oldRange().overlapsLine(ret.line())) {
00050
00051 if (ret == edit->start()) {
00052
00053 if (insertBehavior == SmartCursor::StayOnInsert)
00054 return;
00055 }
00056
00057
00058 Cursor newPos;
00059 if (edit->oldRange().contains(ret)) {
00060 if (insertBehavior == SmartCursor::MoveOnInsert)
00061 ret = edit->newRange().end();
00062 else
00063 ret = edit->start();
00064
00065 } else {
00066 ret += edit->translate();
00067 }
00068
00069 return;
00070 }
00071
00072
00073 ret.setLine(ret.line() + edit->translate().line());
00074 }
00075
00076 #ifdef DEBUG_TRANSLATION
00077 struct KateSmartManager::KateTranslationDebugger {
00078 KateTranslationDebugger(KateSmartManager* manager, KateEditInfo* edit) : m_manager(manager), m_edit(edit) {
00079 manager->m_currentKateTranslationDebugger = this;
00080 foreach(KateSmartRange* range, manager->m_topRanges)
00081 addRange(range);
00082 }
00083
00084 ~KateTranslationDebugger() {
00085 m_manager->m_currentKateTranslationDebugger = 0;
00086 }
00087
00088 void addRange(SmartRange* _range) {
00089
00090 KateSmartRange* range = dynamic_cast<KateSmartRange*>(_range);
00091 Q_ASSERT(range);
00092
00093 RangeTranslation translation;
00094 translation.from = *range;
00095 KTextEditor::Cursor toStart = range->start();
00096 KTextEditor::Cursor toEnd = range->end();
00097
00098 translate(m_edit, toStart, (range->insertBehavior() & SmartRange::ExpandLeft) ? SmartCursor::StayOnInsert : SmartCursor::MoveOnInsert);
00099 translate(m_edit, toEnd, (range->insertBehavior() & SmartRange::ExpandRight) ? SmartCursor::MoveOnInsert : SmartCursor::StayOnInsert);
00100 translation.to = KTextEditor::Range(toStart, toEnd);
00101
00102 m_rangeTranslations[range] = translation;
00103 m_cursorTranslations[&range->smartStart()] = CursorTranslation(range->start(), toStart);
00104 m_cursorTranslations[&range->smartEnd()] = CursorTranslation(range->end(), toEnd);
00105
00106 foreach(SmartRange* child, range->childRanges())
00107 addRange(child);
00108 }
00109
00110 void verifyAll() {
00111 for(QMap<const SmartRange*, RangeTranslation>::iterator it = m_rangeTranslations.begin(); it != m_rangeTranslations.end(); ++it) {
00112 if(*it.key() != it.value().to) {
00113 kDebug() << "mismatch. Translation should be:" << it.value().to << "translation is:" << *it.key() << "from:" << it.value().from;
00114 kDebug() << "edit:" << m_edit->oldRange() << m_edit->newRange();
00115 Q_ASSERT(0);
00116 }
00117 }
00118 }
00119
00120 void verifyChange(SmartCursor* _cursor) {
00121 if(!m_cursorTranslations.contains(_cursor))
00122 return;
00123 return;
00124 KateSmartCursor* cursor = dynamic_cast<KateSmartCursor*>(_cursor);
00125 Q_ASSERT(cursor);
00126 KTextEditor::Cursor realPos( cursor->m_line + cursor->m_smartGroup->m_newStartLine, cursor->m_column);
00127 kDebug() << "changing cursor from" << m_cursorTranslations[cursor].from << "to" << realPos;
00128
00129 if(m_cursorTranslations[cursor].to != realPos) {
00130 kDebug() << "mismatch. Translation of cursor should be:" << m_cursorTranslations[cursor].to << "is:" << realPos << "from:" << m_cursorTranslations[cursor].from;
00131 kDebug() << "edit:" << m_edit->oldRange() << m_edit->newRange();
00132 Q_ASSERT(0);
00133 }
00134 }
00135
00136 struct RangeTranslation {
00137 KTextEditor::Range from, to;
00138 };
00139
00140 struct CursorTranslation {
00141 CursorTranslation() {
00142 }
00143 CursorTranslation(const KTextEditor::Cursor& _from, const KTextEditor::Cursor& _to) : from(_from), to(_to) {
00144 }
00145 KTextEditor::Cursor from, to;
00146 };
00147
00148 QMap<const SmartRange*, RangeTranslation> m_rangeTranslations;
00149 QMap<const SmartCursor*, CursorTranslation> m_cursorTranslations;
00150 KateSmartManager* m_manager;
00151 KateEditInfo* m_edit;
00152 };
00153 #endif
00154 KateSmartManager::KateSmartManager(KateDocument* parent)
00155 : QObject(parent)
00156 , m_firstGroup(new KateSmartGroup(0, 0, 0L, 0L))
00157 , m_invalidGroup(new KateSmartGroup(-1, -1, 0L, 0L))
00158 , m_clearing(false)
00159 , m_currentKateTranslationDebugger(0)
00160 {
00161 connect(doc()->history(), SIGNAL(editDone(KateEditInfo*)), SLOT(slotTextChanged(KateEditInfo*)));
00162
00163 }
00164
00165 KateSmartManager::~KateSmartManager()
00166 {
00167 clear(true);
00168
00169 KateSmartGroup* smartGroup = m_firstGroup;
00170 while (smartGroup) {
00171 KateSmartGroup* toDelete = smartGroup;
00172 smartGroup = smartGroup->next();
00173 delete toDelete;
00174 }
00175
00176 delete m_invalidGroup;
00177 }
00178
00179 KateDocument * KateSmartManager::doc( ) const
00180 {
00181 return static_cast<KateDocument*>(parent());
00182 }
00183
00184 KateSmartCursor * KateSmartManager::newSmartCursor( const Cursor & position, SmartCursor::InsertBehavior insertBehavior, bool internal )
00185 {
00186 QMutexLocker l(internal ? doc()->smartMutex() : 0);
00187
00188 KateSmartCursor* c;
00189 if (usingRevision() != -1 && !internal)
00190 c = new KateSmartCursor(translateFromRevision(position), doc(), insertBehavior);
00191 else
00192 c = new KateSmartCursor(position, doc(), insertBehavior);
00193
00194 if (internal)
00195 c->setInternal();
00196 return c;
00197 }
00198
00199 KateSmartRange * KateSmartManager::newSmartRange( const Range & range, SmartRange * parent, SmartRange::InsertBehaviors insertBehavior, bool internal )
00200 {
00201 QMutexLocker l(internal ? doc()->smartMutex() : 0);
00202
00203 KateSmartRange* newRange;
00204
00205 if (usingRevision() != -1 && !internal)
00206 newRange = new KateSmartRange(translateFromRevision(range), doc(), parent, insertBehavior);
00207 else
00208 newRange = new KateSmartRange(range, doc(), parent, insertBehavior);
00209
00210 if (internal)
00211 newRange->setInternal();
00212 if (!parent)
00213 rangeLostParent(newRange);
00214 return newRange;
00215 }
00216
00217 KateSmartRange * KateSmartManager::newSmartRange( KateSmartCursor * start, KateSmartCursor * end, SmartRange * parent, SmartRange::InsertBehaviors insertBehavior, bool internal )
00218 {
00219 QMutexLocker l(internal ? doc()->smartMutex() : 0);
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 KateSmartRange* newRange = new KateSmartRange(start, end, parent, insertBehavior);
00230 if (internal)
00231 newRange->setInternal();
00232 if (!parent)
00233 rangeLostParent(newRange);
00234 return newRange;
00235 }
00236
00237 void KateSmartGroup::addCursor( KateSmartCursor * cursor)
00238 {
00239 Q_ASSERT(!m_feedbackCursors.contains(cursor));
00240 Q_ASSERT(!m_normalCursors.contains(cursor));
00241
00242 if (cursor->feedbackEnabled())
00243 m_feedbackCursors.insert(cursor);
00244 else
00245 m_normalCursors.insert(cursor);
00246 }
00247
00248 void KateSmartGroup::changeCursorFeedback( KateSmartCursor * cursor )
00249 {
00250 if (!cursor->feedbackEnabled()) {
00251 Q_ASSERT(!m_feedbackCursors.contains(cursor));
00252 Q_ASSERT(m_normalCursors.contains(cursor));
00253 m_normalCursors.remove(cursor);
00254 m_feedbackCursors.insert(cursor);
00255
00256 } else {
00257 Q_ASSERT(m_feedbackCursors.contains(cursor));
00258 Q_ASSERT(!m_normalCursors.contains(cursor));
00259 m_feedbackCursors.remove(cursor);
00260 m_normalCursors.insert(cursor);
00261 }
00262 }
00263
00264 void KateSmartGroup::removeCursor( KateSmartCursor * cursor)
00265 {
00266 if (cursor->feedbackEnabled()) {
00267 Q_ASSERT(m_feedbackCursors.contains(cursor));
00268 Q_ASSERT(!m_normalCursors.contains(cursor));
00269 m_feedbackCursors.remove(cursor);
00270
00271 } else {
00272 Q_ASSERT(!m_feedbackCursors.contains(cursor));
00273 Q_ASSERT(m_normalCursors.contains(cursor));
00274 m_normalCursors.remove(cursor);
00275 }
00276 }
00277
00278 void KateSmartGroup::joined( KateSmartCursor * cursor )
00279 {
00280 addCursor(cursor);
00281 }
00282
00283 void KateSmartGroup::leaving( KateSmartCursor * cursor )
00284 {
00285 removeCursor(cursor);
00286 }
00287
00288 KateSmartGroup * KateSmartManager::groupForLine( int line ) const
00289 {
00290
00291 if (line == -1)
00292 return m_invalidGroup;
00293
00294
00295 KateSmartGroup* smartGroup = m_firstGroup;
00296 while (smartGroup && !smartGroup->containsLine(line))
00297 smartGroup = smartGroup->next();
00298
00299
00300
00301
00302
00303
00304 Q_ASSERT(smartGroup);
00305 return smartGroup;
00306 }
00307
00308 void KateSmartManager::slotTextChanged(KateEditInfo* edit)
00309 {
00310 QMutexLocker lock(doc()->smartMutex());
00311 #ifdef DEBUG_TRANSLATION
00312 KateTranslationDebugger KateTranslationDebugger(this, edit);
00313 #endif
00314 KateSmartGroup* firstSmartGroup = groupForLine(edit->oldRange().start().line());
00315 KateSmartGroup* currentGroup = firstSmartGroup;
00316
00317
00318 int splitEndLine = edit->translate().line() + firstSmartGroup->endLine();
00319
00320 if (edit->translate().line() > 0) {
00321
00322 KateSmartGroup* endGroup = currentGroup->next();
00323
00324 int currentCanExpand = endGroup ? s_maximumGroupSize - currentGroup->length() : s_defaultGroupSize - currentGroup->length();
00325 int expanded = 0;
00326
00327 if (currentCanExpand > 0) {
00328 int expandBy = qMin(edit->translate().line(), currentCanExpand);
00329
00330 currentGroup->setNewEndLine(currentGroup->endLine() + expandBy);
00331
00332 expanded = expandBy;
00333 }
00334
00335 if (expanded < edit->translate().line()) {
00336
00337 int newStartLine, newEndLine;
00338
00339 do {
00340 newStartLine = currentGroup->newEndLine() + 1;
00341 newEndLine = qMin(newStartLine + s_defaultGroupSize - 1, splitEndLine);
00342 currentGroup = new KateSmartGroup(newStartLine, newEndLine, currentGroup, endGroup);
00343
00344 } while (newEndLine < splitEndLine);
00345 }
00346
00347
00348 } else if (edit->translate().line() < 0) {
00349
00350
00351 while (currentGroup->next() && currentGroup->length() + edit->translate().line() < s_minimumGroupSize)
00352 currentGroup->merge();
00353
00354
00355 currentGroup->setNewEndLine(currentGroup->endLine() + edit->translate().line());
00356 }
00357
00358
00359 if (edit->translate().line())
00360 for (KateSmartGroup* smartGroup = currentGroup->next(); smartGroup; smartGroup = smartGroup->next())
00361 smartGroup->translateShifted(*edit);
00362
00363
00364 for (KateSmartGroup* smartGroup = firstSmartGroup; smartGroup; smartGroup = smartGroup->next()) {
00365 if (smartGroup->startLine() > edit->oldRange().end().line())
00366 break;
00367
00368 smartGroup->translateChanged(*edit);
00369 }
00370
00371
00372 bool groupChanged = true;
00373 for (KateSmartGroup* smartGroup = firstSmartGroup; smartGroup; smartGroup = smartGroup->next()) {
00374 if (groupChanged) {
00375 groupChanged = smartGroup->startLine() <= edit->oldRange().end().line();
00376
00377 if (!groupChanged && !edit->translate().line())
00378 break;
00379 }
00380
00381 if (groupChanged)
00382 smartGroup->translatedChanged(*edit);
00383 else
00384 smartGroup->translatedShifted(*edit);
00385 }
00386
00387
00388 for (KateSmartGroup* smartGroup = firstSmartGroup; smartGroup; smartGroup = smartGroup->next()) {
00389 if (smartGroup->startLine() > edit->oldRange().end().line())
00390 break;
00391
00392 smartGroup->translatedChanged2(*edit);
00393 }
00394
00395 #ifdef DEBUG_TRANSLATION
00396 KateTranslationDebugger.verifyAll();
00397 #endif
00398
00399
00400 foreach (KateSmartRange* range, m_topRanges) {
00401 KateSmartRange* mostSpecific = feedbackRange(*edit, range);
00402
00403 if (!mostSpecific)
00404 mostSpecific = range;
00405 range->feedbackMostSpecific(mostSpecific);
00406 }
00407
00408 #ifdef DEBUG_TRANSLATION
00409 KateTranslationDebugger.verifyAll();
00410 #endif
00411
00412
00413 }
00414
00415 KateSmartRange* KateSmartManager::feedbackRange( const KateEditInfo& edit, KateSmartRange * range )
00416 {
00417 KateSmartRange* mostSpecific = 0L;
00418
00419
00420 if ((range->end() < edit.start() && range->kEnd().lastPosition() < edit.start()) ||
00421 (range->end() == edit.start() && range->kEnd().lastPosition() == edit.start() && !range->isEmpty())
00422 ) {
00423
00424 return mostSpecific;
00425 }
00426
00427 foreach (SmartRange* child, range->childRanges())
00428 if (!mostSpecific)
00429 mostSpecific = feedbackRange(edit, static_cast<KateSmartRange*>(child));
00430 else
00431 feedbackRange(edit, static_cast<KateSmartRange*>(child));
00432
00433
00434
00435 if (range->start() > edit.newRange().end() ||
00436 (range->start() == edit.newRange().end() && range->kStart().lastPosition() == edit.oldRange().end()))
00437 {
00438
00439
00440 range->shifted();
00441
00442 } else {
00443
00444
00445 if (!mostSpecific)
00446 if (range->start() < edit.oldRange().start() && range->end() > edit.oldRange().end())
00447 mostSpecific = range;
00448
00449 range->translated(edit);
00450 }
00451
00452 return mostSpecific;
00453 }
00454
00455
00456 void KateSmartGroup::translateChanged( const KateEditInfo& edit)
00457 {
00458
00459
00460 foreach (KateSmartCursor* cursor, m_feedbackCursors)
00461 cursor->translate(edit);
00462
00463 foreach (KateSmartCursor* cursor, m_normalCursors)
00464 cursor->translate(edit);
00465 }
00466
00467 void KateSmartGroup::translateShifted(const KateEditInfo& edit)
00468 {
00469 m_newStartLine = m_startLine + edit.translate().line();
00470 m_newEndLine = m_endLine + edit.translate().line();
00471
00472 }
00473
00474 void KateSmartGroup::translatedChanged(const KateEditInfo& edit)
00475 {
00476 m_startLine = m_newStartLine;
00477 m_endLine = m_newEndLine;
00478
00479 foreach (KateSmartCursor* cursor, m_feedbackCursors)
00480 cursor->translated(edit);
00481 }
00482
00483 void KateSmartGroup::translatedChanged2(const KateEditInfo& edit)
00484 {
00485
00486 QSet<KTextEditor::SmartRange*> rebuilt;
00487
00488 foreach (KateSmartCursor* cursor, m_normalCursors + m_feedbackCursors) {
00489 KTextEditor::SmartRange* range = cursor->smartRange();
00490 if(range) {
00491 KTextEditor::SmartRange* parent = range->parentRange();
00492 if(parent && !rebuilt.contains(parent)) {
00493 rebuilt.insert(parent);
00494 KateSmartRange* kateSmart = dynamic_cast<KateSmartRange*>(parent);
00495 Q_ASSERT(kateSmart);
00496 kateSmart->rebuildChildStructure();
00497 }
00498 }
00499 }
00500 }
00501
00502 void KateSmartGroup::translatedShifted(const KateEditInfo& edit)
00503 {
00504 if (m_startLine != m_newStartLine) {
00505 m_startLine = m_newStartLine;
00506 m_endLine = m_newEndLine;
00507 }
00508
00509 if (edit.translate().line() == 0)
00510 return;
00511
00512
00513 foreach (KateSmartCursor* cursor, m_feedbackCursors)
00514 cursor->shifted();
00515 }
00516
00517 KateSmartGroup::KateSmartGroup( int startLine, int endLine, KateSmartGroup * previous, KateSmartGroup * next )
00518 : m_startLine(startLine)
00519 , m_newStartLine(startLine)
00520 , m_endLine(endLine)
00521 , m_newEndLine(endLine)
00522 , m_next(next)
00523 , m_previous(previous)
00524 {
00525 if (m_previous)
00526 m_previous->setNext(this);
00527
00528 if (m_next)
00529 m_next->setPrevious(this);
00530 }
00531
00532 void KateSmartGroup::merge( )
00533 {
00534 Q_ASSERT(m_next);
00535
00536 foreach (KateSmartCursor* cursor, next()->feedbackCursors())
00537 cursor->migrate(this);
00538 m_feedbackCursors += next()->feedbackCursors();
00539
00540 foreach (KateSmartCursor* cursor, next()->normalCursors())
00541 cursor->migrate(this);
00542 m_normalCursors += next()->normalCursors();
00543
00544 m_newEndLine = m_endLine = next()->endLine();
00545 KateSmartGroup* newNext = next()->next();
00546 delete m_next;
00547 m_next = newNext;
00548 if (m_next)
00549 m_next->setPrevious(this);
00550 }
00551
00552 const QSet< KateSmartCursor * > & KateSmartGroup::feedbackCursors( ) const
00553 {
00554 return m_feedbackCursors;
00555 }
00556
00557 const QSet< KateSmartCursor * > & KateSmartGroup::normalCursors( ) const
00558 {
00559 return m_normalCursors;
00560 }
00561
00562 void KateSmartManager::debugOutput( ) const
00563 {
00564 int groupCount = 1;
00565 KateSmartGroup* currentGroup = m_firstGroup;
00566 while (currentGroup->next()) {
00567 ++groupCount;
00568 currentGroup = currentGroup->next();
00569 }
00570
00571 kDebug() << "KateSmartManager: SmartGroups " << groupCount << " from " << m_firstGroup->startLine() << " to " << currentGroup->endLine();
00572
00573 currentGroup = m_firstGroup;
00574 while (currentGroup) {
00575 currentGroup->debugOutput();
00576 currentGroup = currentGroup->next();
00577 }
00578 }
00579
00580 void KateSmartGroup::debugOutput( ) const
00581 {
00582 kDebug() << " -> KateSmartGroup: from " << startLine() << " to " << endLine() << "; Cursors " << m_normalCursors.count() + m_feedbackCursors.count() << " (" << m_feedbackCursors.count() << " feedback)";
00583 }
00584
00585 void KateSmartManager::verifyCorrect() const
00586 {
00587 KateSmartGroup* currentGroup = groupForLine(0);
00588 Q_ASSERT(currentGroup);
00589 Q_ASSERT(currentGroup == m_firstGroup);
00590
00591 forever {
00592 if (!currentGroup->previous())
00593 Q_ASSERT(currentGroup->startLine() == 0);
00594
00595 foreach (KateSmartCursor* cursor, currentGroup->feedbackCursors()) {
00596 Q_ASSERT(currentGroup->containsLine(cursor->line()));
00597 Q_ASSERT(cursor->smartGroup() == currentGroup);
00598 }
00599
00600 if (!currentGroup->next())
00601 break;
00602
00603 Q_ASSERT(currentGroup->endLine() == currentGroup->next()->startLine() - 1);
00604 Q_ASSERT(currentGroup->next()->previous() == currentGroup);
00605
00606 currentGroup = currentGroup->next();
00607 }
00608
00609 Q_ASSERT(currentGroup->endLine() == doc()->lines() - 1);
00610
00611 kDebug() << "Verified correct." << currentGroup->endLine() << doc()->lines() - 1;
00612 }
00613
00614 void KateSmartManager::rangeGotParent( KateSmartRange * range )
00615 {
00616 Q_ASSERT(m_topRanges.contains(range));
00617 m_topRanges.remove(range);
00618 }
00619
00620 void KateSmartManager::rangeLostParent( KateSmartRange * range )
00621 {
00622 Q_ASSERT(!m_topRanges.contains(range));
00623 m_topRanges.insert(range);
00624 }
00625
00626 void KateSmartManager::rangeDeleted( KateSmartRange* range )
00627 {
00628 emit signalRangeDeleted(range);
00629
00630 if (!range->parentRange())
00631 m_topRanges.remove(range);
00632 }
00633
00634 void KateSmartManager::unbindSmartRange( SmartRange * range )
00635 {
00636 static_cast<KateSmartRange*>(range)->unbindAndDelete();
00637 }
00638
00639 void KateSmartManager::deleteCursors(bool includingInternal)
00640 {
00641 m_invalidGroup->deleteCursors(includingInternal);
00642 for (KateSmartGroup* g = m_firstGroup; g; g = g->next())
00643 g->deleteCursors(includingInternal);
00644 }
00645
00646 void KateSmartGroup::deleteCursors( bool includingInternal )
00647 {
00648 if (includingInternal) {
00649 qDeleteAll(m_feedbackCursors);
00650 m_feedbackCursors.clear();
00651
00652 qDeleteAll(m_normalCursors);
00653 m_normalCursors.clear();
00654
00655 } else {
00656 deleteCursorsInternal(m_feedbackCursors);
00657 deleteCursorsInternal(m_normalCursors);
00658 }
00659 }
00660
00661 void KateSmartGroup::deleteCursorsInternal( QSet< KateSmartCursor * > & set )
00662 {
00663 foreach (KateSmartCursor* c, set.toList()) {
00664 if (!c->range() && !c->isInternal()) {
00665 set.remove(c);
00666 delete c;
00667 }
00668 }
00669 }
00670
00671 void KateSmartManager::deleteRanges( bool includingInternal )
00672 {
00673 foreach (KateSmartRange* range, m_topRanges.toList()) {
00674 if (includingInternal || !range->isInternal()) {
00675 range->deleteChildRanges();
00676 delete range;
00677
00678 if (!includingInternal)
00679 m_topRanges.remove(range);
00680 }
00681 }
00682
00683 if (includingInternal)
00684 m_topRanges.clear();
00685 }
00686
00687 void KateSmartManager::clear( bool includingInternal )
00688 {
00689 deleteRanges(includingInternal);
00690
00691 m_clearing = true;
00692 deleteCursors(includingInternal);
00693 m_clearing = false;
00694 }
00695
00696 void KateSmartManager::useRevision(int revision)
00697 {
00698 if (!m_usingRevision.hasLocalData())
00699 m_usingRevision.setLocalData(new int);
00700
00701 *m_usingRevision.localData() = revision;
00702 }
00703
00704 int KateSmartManager::usingRevision() const
00705 {
00706 if (m_usingRevision.hasLocalData())
00707 return *m_usingRevision.localData();
00708
00709 return -1;
00710 }
00711
00712 void KateSmartManager::releaseRevision(int revision) const
00713 {
00714 doc()->history()->releaseRevision(revision);
00715 }
00716
00717 int KateSmartManager::currentRevision() const
00718 {
00719 return doc()->history()->revision();
00720 }
00721
00722 Cursor KateSmartManager::translateFromRevision(const Cursor& cursor, SmartCursor::InsertBehavior insertBehavior) const
00723 {
00724 Cursor ret = cursor;
00725
00726 foreach (KateEditInfo* edit, doc()->history()->editsBetweenRevisions(usingRevision()))
00727 translate(edit, ret, insertBehavior);
00728
00729 return ret;
00730 }
00731
00732 Range KateSmartManager::translateFromRevision(const Range& range, KTextEditor::SmartRange::InsertBehaviors insertBehavior) const
00733 {
00734 Cursor start = range.start(), end = range.end();
00735
00736 foreach (KateEditInfo* edit, doc()->history()->editsBetweenRevisions(usingRevision())) {
00737 translate(edit, start, insertBehavior & KTextEditor::SmartRange::ExpandLeft ? SmartCursor::StayOnInsert : SmartCursor::MoveOnInsert);
00738 translate(edit, end, insertBehavior & KTextEditor::SmartRange::ExpandRight ? SmartCursor::MoveOnInsert : SmartCursor::StayOnInsert);
00739 }
00740
00741 return Range(start, end);
00742 }
00743
00744 #include "katesmartmanager.moc"