katesupercursor.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2003 Hamish Rodda <rodda@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Library General Public 00006 License version 2 as published by the Free Software Foundation. 00007 00008 This library is distributed in the hope that it will be useful, 00009 but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 Library General Public License for more details. 00012 00013 You should have received a copy of the GNU Library General Public License 00014 along with this library; see the file COPYING.LIB. If not, write to 00015 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00016 Boston, MA 02110-1301, USA. 00017 */ 00018 00019 #include "katesupercursor.h" 00020 #include "katesupercursor.moc" 00021 00022 #include "katedocument.h" 00023 00024 #include <kdebug.h> 00025 00026 #include <qobjectlist.h> 00027 00028 KateSuperCursor::KateSuperCursor(KateDocument* doc, bool privateC, const KateTextCursor& cursor, QObject* parent, const char* name) 00029 : QObject(parent, name) 00030 , KateDocCursor(cursor.line(), cursor.col(), doc) 00031 , Kate::Cursor () 00032 , m_doc (doc) 00033 { 00034 m_moveOnInsert = false; 00035 m_lineRemoved = false; 00036 m_privateCursor = privateC; 00037 00038 m_doc->addSuperCursor (this, privateC); 00039 } 00040 00041 KateSuperCursor::KateSuperCursor(KateDocument* doc, bool privateC, int lineNum, int col, QObject* parent, const char* name) 00042 : QObject(parent, name) 00043 , KateDocCursor(lineNum, col, doc) 00044 , Kate::Cursor () 00045 , m_doc (doc) 00046 { 00047 m_moveOnInsert = false; 00048 m_lineRemoved = false; 00049 m_privateCursor = privateC; 00050 00051 m_doc->addSuperCursor (this, privateC); 00052 } 00053 00054 KateSuperCursor::~KateSuperCursor () 00055 { 00056 m_doc->removeSuperCursor (this, m_privateCursor); 00057 } 00058 00059 void KateSuperCursor::position(uint *pline, uint *pcol) const 00060 { 00061 KateDocCursor::position(pline, pcol); 00062 } 00063 00064 bool KateSuperCursor::setPosition(uint line, uint col) 00065 { 00066 if (line == uint(-2) && col == uint(-2)) { delete this; return true; } 00067 return KateDocCursor::setPosition(line, col); 00068 } 00069 00070 bool KateSuperCursor::insertText(const QString& s) 00071 { 00072 return KateDocCursor::insertText(s); 00073 } 00074 00075 bool KateSuperCursor::removeText(uint nbChar) 00076 { 00077 return KateDocCursor::removeText(nbChar); 00078 } 00079 00080 QChar KateSuperCursor::currentChar() const 00081 { 00082 return KateDocCursor::currentChar(); 00083 } 00084 00085 bool KateSuperCursor::atStartOfLine() const 00086 { 00087 return col() == 0; 00088 } 00089 00090 bool KateSuperCursor::atEndOfLine() const 00091 { 00092 return col() >= (int)m_doc->kateTextLine(line())->length(); 00093 } 00094 00095 bool KateSuperCursor::moveOnInsert() const 00096 { 00097 return m_moveOnInsert; 00098 } 00099 00100 void KateSuperCursor::setMoveOnInsert(bool moveOnInsert) 00101 { 00102 m_moveOnInsert = moveOnInsert; 00103 } 00104 00105 void KateSuperCursor::setLine(int lineNum) 00106 { 00107 int tempLine = line(), tempcol = col(); 00108 KateDocCursor::setLine(lineNum); 00109 00110 if (tempLine != line() || tempcol != col()) 00111 emit positionDirectlyChanged(); 00112 } 00113 00114 void KateSuperCursor::setCol(int colNum) 00115 { 00116 KateDocCursor::setCol(colNum); 00117 } 00118 00119 void KateSuperCursor::setPos(const KateTextCursor& pos) 00120 { 00121 KateDocCursor::setPos(pos); 00122 } 00123 00124 void KateSuperCursor::setPos(int lineNum, int colNum) 00125 { 00126 KateDocCursor::setPos(lineNum, colNum); 00127 } 00128 00129 void KateSuperCursor::editTextInserted(uint line, uint col, uint len) 00130 { 00131 if (m_line == int(line)) 00132 { 00133 if ((m_col > int(col)) || (m_moveOnInsert && (m_col == int(col)))) 00134 { 00135 bool insertedAt = m_col == int(col); 00136 00137 m_col += len; 00138 00139 if (insertedAt) 00140 emit charInsertedAt(); 00141 00142 emit positionChanged(); 00143 return; 00144 } 00145 } 00146 00147 emit positionUnChanged(); 00148 } 00149 00150 void KateSuperCursor::editTextRemoved(uint line, uint col, uint len) 00151 { 00152 if (m_line == int(line)) 00153 { 00154 if (m_col > int(col)) 00155 { 00156 if (m_col > int(col + len)) 00157 { 00158 m_col -= len; 00159 } 00160 else 00161 { 00162 bool prevCharDeleted = m_col == int(col + len); 00163 00164 m_col = col; 00165 00166 if (prevCharDeleted) 00167 emit charDeletedBefore(); 00168 else 00169 emit positionDeleted(); 00170 } 00171 00172 emit positionChanged(); 00173 return; 00174 00175 } 00176 else if (m_col == int(col)) 00177 { 00178 emit charDeletedAfter(); 00179 } 00180 } 00181 00182 emit positionUnChanged(); 00183 } 00184 00185 void KateSuperCursor::editLineWrapped(uint line, uint col, bool newLine) 00186 { 00187 if (newLine) 00188 { 00189 if (m_line > int(line) || (m_line == int(line) && m_col >= int(col))) 00190 { 00191 if(m_line == int(line)) 00192 m_col -= col; 00193 m_line++; 00194 00195 emit positionChanged(); 00196 return; 00197 } 00198 } 00199 else if ( (m_line == int(line)) && (m_col > int(col)) || (m_moveOnInsert && (m_col == int(col))) ) 00200 { 00201 m_line++; 00202 m_col -= col; 00203 00204 emit positionChanged(); 00205 return; 00206 } 00207 00208 emit positionUnChanged(); 00209 } 00210 00211 void KateSuperCursor::editLineUnWrapped(uint line, uint col, bool removeLine, uint length) 00212 { 00213 if (removeLine && (m_line > int(line+1))) 00214 { 00215 m_line--; 00216 00217 emit positionChanged(); 00218 return; 00219 } 00220 else if ( (m_line == int(line+1)) && (removeLine || (m_col < int(length))) ) 00221 { 00222 m_line = line; 00223 m_col += col; 00224 00225 emit positionChanged(); 00226 return; 00227 } 00228 else if ( (m_line == int(line+1)) && (m_col >= int(length)) ) 00229 { 00230 m_col -= length; 00231 00232 emit positionChanged(); 00233 return; 00234 } 00235 00236 emit positionUnChanged(); 00237 } 00238 00239 void KateSuperCursor::editLineInserted (uint line) 00240 { 00241 if (m_line >= int(line)) 00242 { 00243 m_line++; 00244 00245 emit positionChanged(); 00246 return; 00247 } 00248 00249 emit positionUnChanged(); 00250 } 00251 00252 void KateSuperCursor::editLineRemoved(uint line) 00253 { 00254 if (m_line > int(line)) 00255 { 00256 m_line--; 00257 00258 emit positionChanged(); 00259 return; 00260 } 00261 else if (m_line == int(line)) 00262 { 00263 m_line = (line <= m_doc->lastLine()) ? line : (line - 1); 00264 m_col = 0; 00265 00266 emit positionDeleted(); 00267 00268 emit positionChanged(); 00269 return; 00270 } 00271 00272 emit positionUnChanged(); 00273 } 00274 00275 KateSuperCursor::operator QString() 00276 { 00277 return QString("[%1,%1]").arg(line()).arg(col()); 00278 } 00279 00280 KateSuperRange::KateSuperRange(KateSuperCursor* start, KateSuperCursor* end, QObject* parent, const char* name) 00281 : QObject(parent, name) 00282 , m_start(start) 00283 , m_end(end) 00284 , m_evaluate(false) 00285 , m_startChanged(false) 00286 , m_endChanged(false) 00287 , m_deleteCursors(false) 00288 , m_allowZeroLength(false) 00289 { 00290 init(); 00291 } 00292 00293 KateSuperRange::KateSuperRange(KateDocument* doc, const KateRange& range, QObject* parent, const char* name) 00294 : QObject(parent, name) 00295 , m_start(new KateSuperCursor(doc, true, range.start())) 00296 , m_end(new KateSuperCursor(doc, true, range.end())) 00297 , m_evaluate(false) 00298 , m_startChanged(false) 00299 , m_endChanged(false) 00300 , m_deleteCursors(true) 00301 , m_allowZeroLength(false) 00302 { 00303 init(); 00304 } 00305 00306 KateSuperRange::KateSuperRange(KateDocument* doc, const KateTextCursor& start, const KateTextCursor& end, QObject* parent, const char* name) 00307 : QObject(parent, name) 00308 , m_start(new KateSuperCursor(doc, true, start)) 00309 , m_end(new KateSuperCursor(doc, true, end)) 00310 , m_evaluate(false) 00311 , m_startChanged(false) 00312 , m_endChanged(false) 00313 , m_deleteCursors(true) 00314 , m_allowZeroLength(false) 00315 { 00316 init(); 00317 } 00318 00319 void KateSuperRange::init() 00320 { 00321 Q_ASSERT(isValid()); 00322 if (!isValid()) 00323 kdDebug(13020) << superStart() << " " << superEnd() << endl; 00324 00325 insertChild(m_start); 00326 insertChild(m_end); 00327 00328 setBehaviour(DoNotExpand); 00329 00330 // Not necessarily the best implementation 00331 connect(m_start, SIGNAL(positionDirectlyChanged()), SIGNAL(contentsChanged())); 00332 connect(m_end, SIGNAL(positionDirectlyChanged()), SIGNAL(contentsChanged())); 00333 00334 connect(m_start, SIGNAL(positionChanged()), SLOT(slotEvaluateChanged())); 00335 connect(m_end, SIGNAL(positionChanged()), SLOT(slotEvaluateChanged())); 00336 connect(m_start, SIGNAL(positionUnChanged()), SLOT(slotEvaluateUnChanged())); 00337 connect(m_end, SIGNAL(positionUnChanged()), SLOT(slotEvaluateUnChanged())); 00338 connect(m_start, SIGNAL(positionDeleted()), SIGNAL(boundaryDeleted())); 00339 connect(m_end, SIGNAL(positionDeleted()), SIGNAL(boundaryDeleted())); 00340 } 00341 00342 KateSuperRange::~KateSuperRange() 00343 { 00344 if (m_deleteCursors) 00345 { 00346 //insertChild(m_start); 00347 //insertChild(m_end); 00348 delete m_start; 00349 delete m_end; 00350 } 00351 } 00352 00353 KateTextCursor& KateSuperRange::start() 00354 { 00355 return *m_start; 00356 } 00357 00358 const KateTextCursor& KateSuperRange::start() const 00359 { 00360 return *m_start; 00361 } 00362 00363 KateTextCursor& KateSuperRange::end() 00364 { 00365 return *m_end; 00366 } 00367 00368 const KateTextCursor& KateSuperRange::end() const 00369 { 00370 return *m_end; 00371 } 00372 00373 KateSuperCursor& KateSuperRange::superStart() 00374 { 00375 return *m_start; 00376 } 00377 00378 const KateSuperCursor& KateSuperRange::superStart() const 00379 { 00380 return *m_start; 00381 } 00382 00383 KateSuperCursor& KateSuperRange::superEnd() 00384 { 00385 return *m_end; 00386 } 00387 00388 const KateSuperCursor& KateSuperRange::superEnd() const 00389 { 00390 return *m_end; 00391 } 00392 00393 int KateSuperRange::behaviour() const 00394 { 00395 return (m_start->moveOnInsert() ? DoNotExpand : ExpandLeft) | (m_end->moveOnInsert() ? ExpandRight : DoNotExpand); 00396 } 00397 00398 void KateSuperRange::setBehaviour(int behaviour) 00399 { 00400 m_start->setMoveOnInsert(behaviour & ExpandLeft); 00401 m_end->setMoveOnInsert(!(behaviour & ExpandRight)); 00402 } 00403 00404 bool KateSuperRange::isValid() const 00405 { 00406 return superStart() <= superEnd(); 00407 } 00408 00409 bool KateSuperRange::owns(const KateTextCursor& cursor) const 00410 { 00411 if (!includes(cursor)) return false; 00412 00413 if (children()) 00414 for (QObjectListIt it(*children()); *it; ++it) 00415 if ((*it)->inherits("KateSuperRange")) 00416 if (static_cast<KateSuperRange*>(*it)->owns(cursor)) 00417 return false; 00418 00419 return true; 00420 } 00421 00422 bool KateSuperRange::includes(const KateTextCursor& cursor) const 00423 { 00424 return isValid() && cursor >= superStart() && cursor < superEnd(); 00425 } 00426 00427 bool KateSuperRange::includes(uint lineNum) const 00428 { 00429 return isValid() && (int)lineNum >= superStart().line() && (int)lineNum <= superEnd().line(); 00430 } 00431 00432 bool KateSuperRange::includesWholeLine(uint lineNum) const 00433 { 00434 return isValid() && ((int)lineNum > superStart().line() || ((int)lineNum == superStart().line() && superStart().atStartOfLine())) && ((int)lineNum < superEnd().line() || ((int)lineNum == superEnd().line() && superEnd().atEndOfLine())); 00435 } 00436 00437 bool KateSuperRange::boundaryAt(const KateTextCursor& cursor) const 00438 { 00439 return isValid() && (cursor == superStart() || cursor == superEnd()); 00440 } 00441 00442 bool KateSuperRange::boundaryOn(uint lineNum) const 00443 { 00444 return isValid() && (superStart().line() == (int)lineNum || superEnd().line() == (int)lineNum); 00445 } 00446 00447 void KateSuperRange::slotEvaluateChanged() 00448 { 00449 if (sender() == static_cast<QObject*>(m_start)) { 00450 if (m_evaluate) { 00451 if (!m_endChanged) { 00452 // Only one was changed 00453 evaluateEliminated(); 00454 00455 } else { 00456 // Both were changed 00457 evaluatePositionChanged(); 00458 m_endChanged = false; 00459 } 00460 00461 } else { 00462 m_startChanged = true; 00463 } 00464 00465 } else { 00466 if (m_evaluate) { 00467 if (!m_startChanged) { 00468 // Only one was changed 00469 evaluateEliminated(); 00470 00471 } else { 00472 // Both were changed 00473 evaluatePositionChanged(); 00474 m_startChanged = false; 00475 } 00476 00477 } else { 00478 m_endChanged = true; 00479 } 00480 } 00481 00482 m_evaluate = !m_evaluate; 00483 } 00484 00485 void KateSuperRange::slotEvaluateUnChanged() 00486 { 00487 if (sender() == static_cast<QObject*>(m_start)) { 00488 if (m_evaluate) { 00489 if (m_endChanged) { 00490 // Only one changed 00491 evaluateEliminated(); 00492 m_endChanged = false; 00493 00494 } else { 00495 // Neither changed 00496 emit positionUnChanged(); 00497 } 00498 } 00499 00500 } else { 00501 if (m_evaluate) { 00502 if (m_startChanged) { 00503 // Only one changed 00504 evaluateEliminated(); 00505 m_startChanged = false; 00506 00507 } else { 00508 // Neither changed 00509 emit positionUnChanged(); 00510 } 00511 } 00512 } 00513 00514 m_evaluate = !m_evaluate; 00515 } 00516 00517 void KateSuperRange::slotTagRange() 00518 { 00519 emit tagRange(this); 00520 } 00521 00522 void KateSuperRange::evaluateEliminated() 00523 { 00524 if (superStart() == superEnd()) { 00525 if (!m_allowZeroLength) emit eliminated(); 00526 } 00527 else 00528 emit contentsChanged(); 00529 } 00530 00531 void KateSuperRange::evaluatePositionChanged() 00532 { 00533 if (superStart() == superEnd()) 00534 emit eliminated(); 00535 else 00536 emit positionChanged(); 00537 } 00538 00539 int KateSuperCursorList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2) 00540 { 00541 if (*(static_cast<KateSuperCursor*>(item1)) == *(static_cast<KateSuperCursor*>(item2))) 00542 return 0; 00543 00544 return *(static_cast<KateSuperCursor*>(item1)) < *(static_cast<KateSuperCursor*>(item2)) ? -1 : 1; 00545 } 00546 00547 KateSuperRangeList::KateSuperRangeList(bool autoManage, QObject* parent, const char* name) 00548 : QObject(parent, name) 00549 , m_autoManage(autoManage) 00550 , m_connect(true) 00551 , m_trackingBoundaries(false) 00552 { 00553 setAutoManage(autoManage); 00554 } 00555 00556 KateSuperRangeList::KateSuperRangeList(const QPtrList<KateSuperRange>& rangeList, QObject* parent, const char* name) 00557 : QObject(parent, name) 00558 , m_autoManage(false) 00559 , m_connect(false) 00560 , m_trackingBoundaries(false) 00561 { 00562 appendList(rangeList); 00563 } 00564 00565 void KateSuperRangeList::appendList(const QPtrList<KateSuperRange>& rangeList) 00566 { 00567 for (QPtrListIterator<KateSuperRange> it = rangeList; *it; ++it) 00568 append(*it); 00569 } 00570 00571 void KateSuperRangeList::clear() 00572 { 00573 for (KateSuperRange* range = first(); range; range = next()) 00574 emit rangeEliminated(range); 00575 00576 QPtrList<KateSuperRange>::clear(); 00577 } 00578 00579 void KateSuperRangeList::connectAll() 00580 { 00581 if (!m_connect) { 00582 m_connect = true; 00583 for (KateSuperRange* range = first(); range; range = next()) { 00584 connect(range, SIGNAL(destroyed(QObject*)), SLOT(slotDeleted(QObject*))); 00585 connect(range, SIGNAL(eliminated()), SLOT(slotEliminated())); 00586 } 00587 } 00588 } 00589 00590 bool KateSuperRangeList::autoManage() const 00591 { 00592 return m_autoManage; 00593 } 00594 00595 void KateSuperRangeList::setAutoManage(bool autoManage) 00596 { 00597 m_autoManage = autoManage; 00598 setAutoDelete(m_autoManage); 00599 } 00600 00601 QPtrList<KateSuperRange> KateSuperRangeList::rangesIncluding(const KateTextCursor& cursor) 00602 { 00603 sort(); 00604 00605 QPtrList<KateSuperRange> ret; 00606 00607 for (KateSuperRange* r = first(); r; r = next()) 00608 if (r->includes(cursor)) 00609 ret.append(r); 00610 00611 return ret; 00612 } 00613 00614 QPtrList<KateSuperRange> KateSuperRangeList::rangesIncluding(uint line) 00615 { 00616 sort(); 00617 00618 QPtrList<KateSuperRange> ret; 00619 00620 for (KateSuperRange* r = first(); r; r = next()) 00621 if (r->includes(line)) 00622 ret.append(r); 00623 00624 return ret; 00625 } 00626 00627 bool KateSuperRangeList::rangesInclude(const KateTextCursor& cursor) 00628 { 00629 for (KateSuperRange* r = first(); r; r = next()) 00630 if (r->includes(cursor)) 00631 return true; 00632 00633 return false; 00634 } 00635 00636 void KateSuperRangeList::slotEliminated() 00637 { 00638 if (sender()) { 00639 KateSuperRange* range = static_cast<KateSuperRange*>(const_cast<QObject*>(sender())); 00640 emit rangeEliminated(range); 00641 00642 if (m_trackingBoundaries) { 00643 m_columnBoundaries.removeRef(range->m_start); 00644 m_columnBoundaries.removeRef(range->m_end); 00645 } 00646 00647 if (m_autoManage) 00648 removeRef(range); 00649 00650 if (!count()) 00651 emit listEmpty(); 00652 } 00653 } 00654 00655 void KateSuperRangeList::slotDeleted(QObject* range) 00656 { 00657 //kdDebug(13020)<<"KateSuperRangeList::slotDeleted"<<endl; 00658 KateSuperRange* r = static_cast<KateSuperRange*>(range); 00659 00660 if (m_trackingBoundaries) { 00661 m_columnBoundaries.removeRef(r->m_start); 00662 m_columnBoundaries.removeRef(r->m_end); 00663 } 00664 00665 int index = findRef(r); 00666 if (index != -1) 00667 take(index); 00668 //else kdDebug(13020)<<"Range not found in list"<<endl; 00669 00670 if (!count()) 00671 emit listEmpty(); 00672 } 00673 00674 KateSuperCursor* KateSuperRangeList::firstBoundary(const KateTextCursor* start) 00675 { 00676 if (!m_trackingBoundaries) { 00677 m_trackingBoundaries = true; 00678 00679 for (KateSuperRange* r = first(); r; r = next()) { 00680 m_columnBoundaries.append(&(r->superStart())); 00681 m_columnBoundaries.append(&(r->superEnd())); 00682 } 00683 } 00684 00685 m_columnBoundaries.sort(); 00686 00687 if (start) 00688 // OPTIMISE: QMap with QPtrList for each line? (==> sorting issues :( ) 00689 for (KateSuperCursor* c = m_columnBoundaries.first(); c; c = m_columnBoundaries.next()) 00690 if (*start <= *c) 00691 break; 00692 00693 return m_columnBoundaries.current(); 00694 } 00695 00696 KateSuperCursor* KateSuperRangeList::nextBoundary() 00697 { 00698 KateSuperCursor* current = m_columnBoundaries.current(); 00699 00700 // make sure the new cursor is after the current cursor; multiple cursors with the same position can be in the list. 00701 if (current) 00702 while (m_columnBoundaries.next()) 00703 if (*(m_columnBoundaries.current()) != *current) 00704 break; 00705 00706 return m_columnBoundaries.current(); 00707 } 00708 00709 KateSuperCursor* KateSuperRangeList::currentBoundary() 00710 { 00711 return m_columnBoundaries.current(); 00712 } 00713 00714 int KateSuperRangeList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2) 00715 { 00716 if (static_cast<KateSuperRange*>(item1)->superStart() == static_cast<KateSuperRange*>(item2)->superStart()) { 00717 if (static_cast<KateSuperRange*>(item1)->superEnd() == static_cast<KateSuperRange*>(item2)->superEnd()) { 00718 return 0; 00719 } else { 00720 return static_cast<KateSuperRange*>(item1)->superEnd() < static_cast<KateSuperRange*>(item2)->superEnd() ? -1 : 1; 00721 } 00722 } 00723 00724 return static_cast<KateSuperRange*>(item1)->superStart() < static_cast<KateSuperRange*>(item2)->superStart() ? -1 : 1; 00725 } 00726 00727 QPtrCollection::Item KateSuperRangeList::newItem(QPtrCollection::Item d) 00728 { 00729 if (m_connect) { 00730 connect(static_cast<KateSuperRange*>(d), SIGNAL(destroyed(QObject*)), SLOT(slotDeleted(QObject*))); 00731 connect(static_cast<KateSuperRange*>(d), SIGNAL(eliminated()), SLOT(slotEliminated())); 00732 connect(static_cast<KateSuperRange*>(d), SIGNAL(tagRange(KateSuperRange*)), SIGNAL(tagRange(KateSuperRange*))); 00733 00734 // HACK HACK 00735 static_cast<KateSuperRange*>(d)->slotTagRange(); 00736 } 00737 00738 if (m_trackingBoundaries) { 00739 m_columnBoundaries.append(&(static_cast<KateSuperRange*>(d)->superStart())); 00740 m_columnBoundaries.append(&(static_cast<KateSuperRange*>(d)->superEnd())); 00741 } 00742 00743 return QPtrList<KateSuperRange>::newItem(d); 00744 } 00745 00746 // kate: space-indent on; indent-width 2; replace-tabs on;