kate Library API Documentation

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., 59 Temple Place - Suite 330,
00016    Boston, MA 02111-1307, 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 && (m_line > int(line)))
00188   {
00189     m_line++;
00190 
00191     emit positionChanged();
00192     return;
00193   }
00194   else if ( (m_line == int(line)) && (m_col >= int(col)) )
00195   {
00196     m_line++;
00197     m_col -= col;
00198 
00199     emit positionChanged();
00200     return;
00201   }
00202 
00203   emit positionUnChanged();
00204 }
00205 
00206 void KateSuperCursor::editLineUnWrapped(uint line, uint col, bool removeLine, uint length)
00207 {
00208   if (removeLine && (m_line > int(line+1)))
00209   {
00210     m_line--;
00211 
00212     emit positionChanged();
00213     return;
00214   }
00215   else if ( (m_line == int(line+1)) && (removeLine || (m_col < int(length))) )
00216   {
00217     m_line = line;
00218     m_col += col;
00219 
00220     emit positionChanged();
00221     return;
00222   }
00223   else if ( (m_line == int(line+1)) && (m_col >= int(length)) )
00224   {
00225     m_col -= length;
00226 
00227     emit positionChanged();
00228     return;
00229   }
00230 
00231   emit positionUnChanged();
00232 }
00233 
00234 void KateSuperCursor::editLineInserted (uint line)
00235 {
00236   if (m_line >= int(line))
00237   {
00238     m_line++;
00239 
00240     emit positionChanged();
00241     return;
00242   }
00243 
00244   emit positionUnChanged();
00245 }
00246 
00247 void KateSuperCursor::editLineRemoved(uint line)
00248 {
00249   if (m_line > int(line))
00250   {
00251     m_line--;
00252 
00253     emit positionChanged();
00254     return;
00255   }
00256   else if (m_line == int(line))
00257   {
00258     m_line = (line < m_doc->lastLine()) ? line : (line - 1);
00259     m_col = 0;
00260 
00261     emit positionDeleted();
00262 
00263     emit positionChanged();
00264     return;
00265   }
00266 
00267   emit positionUnChanged();
00268 }
00269 
00270 KateSuperCursor::operator QString()
00271 {
00272   return QString("[%1,%1]").arg(line()).arg(col());
00273 }
00274 
00275 KateSuperRange::KateSuperRange(KateSuperCursor* start, KateSuperCursor* end, QObject* parent, const char* name)
00276   : QObject(parent, name)
00277   , m_start(start)
00278   , m_end(end)
00279   , m_evaluate(false)
00280   , m_startChanged(false)
00281   , m_endChanged(false)
00282   , m_deleteCursors(false)
00283 {
00284   init();
00285 }
00286 
00287 KateSuperRange::KateSuperRange(KateDocument* doc, const KateRange& range, QObject* parent, const char* name)
00288   : QObject(parent, name)
00289   , m_start(new KateSuperCursor(doc, true, range.start()))
00290   , m_end(new KateSuperCursor(doc, true, range.end()))
00291   , m_evaluate(false)
00292   , m_startChanged(false)
00293   , m_endChanged(false)
00294   , m_deleteCursors(true)
00295 {
00296   init();
00297 }
00298 
00299 KateSuperRange::KateSuperRange(KateDocument* doc, const KateTextCursor& start, const KateTextCursor& end, QObject* parent, const char* name)
00300   : QObject(parent, name)
00301   , m_start(new KateSuperCursor(doc, true, start))
00302   , m_end(new KateSuperCursor(doc, true, end))
00303   , m_evaluate(false)
00304   , m_startChanged(false)
00305   , m_endChanged(false)
00306   , m_deleteCursors(true)
00307 {
00308   init();
00309 }
00310 
00311 void KateSuperRange::init()
00312 {
00313   Q_ASSERT(isValid());
00314   if (!isValid())
00315     kdDebug() << superStart() << " " << superEnd() << endl;
00316 
00317   insertChild(m_start);
00318   insertChild(m_end);
00319 
00320   setBehaviour(DoNotExpand);
00321 
00322   // Not necessarily the best implementation
00323   connect(m_start, SIGNAL(positionDirectlyChanged()),  SIGNAL(contentsChanged()));
00324   connect(m_end, SIGNAL(positionDirectlyChanged()),  SIGNAL(contentsChanged()));
00325 
00326   connect(m_start, SIGNAL(positionChanged()),  SLOT(slotEvaluateChanged()));
00327   connect(m_end, SIGNAL(positionChanged()),  SLOT(slotEvaluateChanged()));
00328   connect(m_start, SIGNAL(positionUnChanged()), SLOT(slotEvaluateUnChanged()));
00329   connect(m_end, SIGNAL(positionUnChanged()), SLOT(slotEvaluateUnChanged()));
00330   connect(m_start, SIGNAL(positionDeleted()), SIGNAL(boundaryDeleted()));
00331   connect(m_end, SIGNAL(positionDeleted()), SIGNAL(boundaryDeleted()));
00332 }
00333 
00334 KateSuperRange::~KateSuperRange()
00335 {
00336   if (m_deleteCursors)
00337   {
00338     delete m_start;
00339     delete m_end;
00340   }
00341 }
00342 
00343 KateTextCursor& KateSuperRange::start()
00344 {
00345   return *m_start;
00346 }
00347 
00348 const KateTextCursor& KateSuperRange::start() const
00349 {
00350   return *m_start;
00351 }
00352 
00353 KateTextCursor& KateSuperRange::end()
00354 {
00355   return *m_end;
00356 }
00357 
00358 const KateTextCursor& KateSuperRange::end() const
00359 {
00360   return *m_end;
00361 }
00362 
00363 KateSuperCursor& KateSuperRange::superStart()
00364 {
00365   return *m_start;
00366 }
00367 
00368 const KateSuperCursor& KateSuperRange::superStart() const
00369 {
00370   return *m_start;
00371 }
00372 
00373 KateSuperCursor& KateSuperRange::superEnd()
00374 {
00375   return *m_end;
00376 }
00377 
00378 const KateSuperCursor& KateSuperRange::superEnd() const
00379 {
00380   return *m_end;
00381 }
00382 
00383 int KateSuperRange::behaviour() const
00384 {
00385   return (m_start->moveOnInsert() ? DoNotExpand : ExpandLeft) | (m_end->moveOnInsert() ? ExpandRight : DoNotExpand);
00386 }
00387 
00388 void KateSuperRange::setBehaviour(int behaviour)
00389 {
00390   m_start->setMoveOnInsert(behaviour & ExpandLeft);
00391   m_end->setMoveOnInsert(!(behaviour & ExpandRight));
00392 }
00393 
00394 bool KateSuperRange::isValid() const
00395 {
00396   return superStart() <= superEnd();
00397 }
00398 
00399 bool KateSuperRange::owns(const KateTextCursor& cursor) const
00400 {
00401   if (!includes(cursor)) return false;
00402 
00403   if (children())
00404     for (QObjectListIt it(*children()); *it; ++it)
00405       if ((*it)->inherits("KateSuperRange"))
00406         if (static_cast<KateSuperRange*>(*it)->owns(cursor))
00407           return false;
00408 
00409   return true;
00410 }
00411 
00412 bool KateSuperRange::includes(const KateTextCursor& cursor) const
00413 {
00414   return isValid() && cursor >= superStart() && cursor < superEnd();
00415 }
00416 
00417 bool KateSuperRange::includes(uint lineNum) const
00418 {
00419   return isValid() && (int)lineNum >= superStart().line() && (int)lineNum <= superEnd().line();
00420 }
00421 
00422 bool KateSuperRange::includesWholeLine(uint lineNum) const
00423 {
00424   return isValid() && ((int)lineNum > superStart().line() || ((int)lineNum == superStart().line() && superStart().atStartOfLine())) && ((int)lineNum < superEnd().line() || ((int)lineNum == superEnd().line() && superEnd().atEndOfLine()));
00425 }
00426 
00427 bool KateSuperRange::boundaryAt(const KateTextCursor& cursor) const
00428 {
00429   return isValid() && (cursor == superStart() || cursor == superEnd());
00430 }
00431 
00432 bool KateSuperRange::boundaryOn(uint lineNum) const
00433 {
00434   return isValid() && (superStart().line() == (int)lineNum || superEnd().line() == (int)lineNum);
00435 }
00436 
00437 void KateSuperRange::slotEvaluateChanged()
00438 {
00439   if (sender() == static_cast<QObject*>(m_start)) {
00440     if (m_evaluate) {
00441       if (!m_endChanged) {
00442         // Only one was changed
00443         evaluateEliminated();
00444 
00445       } else {
00446         // Both were changed
00447         evaluatePositionChanged();
00448         m_endChanged = false;
00449       }
00450 
00451     } else {
00452       m_startChanged = true;
00453     }
00454 
00455   } else {
00456     if (m_evaluate) {
00457       if (!m_startChanged) {
00458         // Only one was changed
00459         evaluateEliminated();
00460 
00461       } else {
00462         // Both were changed
00463         evaluatePositionChanged();
00464         m_startChanged = false;
00465       }
00466 
00467     } else {
00468       m_endChanged = true;
00469     }
00470   }
00471 
00472   m_evaluate = !m_evaluate;
00473 }
00474 
00475 void KateSuperRange::slotEvaluateUnChanged()
00476 {
00477   if (sender() == static_cast<QObject*>(m_start)) {
00478     if (m_evaluate) {
00479       if (m_endChanged) {
00480         // Only one changed
00481         evaluateEliminated();
00482         m_endChanged = false;
00483 
00484       } else {
00485         // Neither changed
00486         emit positionUnChanged();
00487       }
00488     }
00489 
00490   } else {
00491     if (m_evaluate) {
00492       if (m_startChanged) {
00493         // Only one changed
00494         evaluateEliminated();
00495         m_startChanged = false;
00496 
00497       } else {
00498         // Neither changed
00499         emit positionUnChanged();
00500       }
00501     }
00502   }
00503 
00504   m_evaluate = !m_evaluate;
00505 }
00506 
00507 void KateSuperRange::slotTagRange()
00508 {
00509   emit tagRange(this);
00510 }
00511 
00512 void KateSuperRange::evaluateEliminated()
00513 {
00514   if (superStart() == superEnd())
00515     emit eliminated();
00516   else
00517     emit contentsChanged();
00518 }
00519 
00520 void KateSuperRange::evaluatePositionChanged()
00521 {
00522   if (superStart() == superEnd())
00523     emit eliminated();
00524   else
00525     emit positionChanged();
00526 }
00527 
00528 int KateSuperCursorList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2)
00529 {
00530   if (*(static_cast<KateSuperCursor*>(item1)) == *(static_cast<KateSuperCursor*>(item2)))
00531     return 0;
00532 
00533   return *(static_cast<KateSuperCursor*>(item1)) < *(static_cast<KateSuperCursor*>(item2)) ? -1 : 1;
00534 }
00535 
00536 KateSuperRangeList::KateSuperRangeList(bool autoManage, QObject* parent, const char* name)
00537   : QObject(parent, name)
00538   , m_autoManage(autoManage)
00539   , m_connect(true)
00540   , m_trackingBoundaries(false)
00541 {
00542   setAutoManage(autoManage);
00543 }
00544 
00545 KateSuperRangeList::KateSuperRangeList(const QPtrList<KateSuperRange>& rangeList, QObject* parent, const char* name)
00546   : QObject(parent, name)
00547   , m_autoManage(false)
00548   , m_connect(false)
00549   , m_trackingBoundaries(false)
00550 {
00551   appendList(rangeList);
00552 }
00553 
00554 void KateSuperRangeList::appendList(const QPtrList<KateSuperRange>& rangeList)
00555 {
00556   for (QPtrListIterator<KateSuperRange> it = rangeList; *it; ++it)
00557     append(*it);
00558 }
00559 
00560 void KateSuperRangeList::clear()
00561 {
00562   for (KateSuperRange* range = first(); range; range = next())
00563     emit rangeEliminated(range);
00564 
00565   QPtrList<KateSuperRange>::clear();
00566 }
00567 
00568 void KateSuperRangeList::connectAll()
00569 {
00570   if (!m_connect) {
00571     m_connect = true;
00572     for (KateSuperRange* range = first(); range; range = next()) {
00573       connect(range, SIGNAL(destroyed(QObject*)), SLOT(slotDeleted(QObject*)));
00574       connect(range, SIGNAL(eliminated()), SLOT(slotEliminated()));
00575     }
00576   }
00577 }
00578 
00579 bool KateSuperRangeList::autoManage() const
00580 {
00581   return m_autoManage;
00582 }
00583 
00584 void KateSuperRangeList::setAutoManage(bool autoManage)
00585 {
00586   m_autoManage = autoManage;
00587   setAutoDelete(m_autoManage);
00588 }
00589 
00590 QPtrList<KateSuperRange> KateSuperRangeList::rangesIncluding(const KateTextCursor& cursor)
00591 {
00592   sort();
00593 
00594   QPtrList<KateSuperRange> ret;
00595 
00596   for (KateSuperRange* r = first(); r; r = next())
00597     if (r->includes(cursor))
00598       ret.append(r);
00599 
00600   return ret;
00601 }
00602 
00603 QPtrList<KateSuperRange> KateSuperRangeList::rangesIncluding(uint line)
00604 {
00605   sort();
00606 
00607   QPtrList<KateSuperRange> ret;
00608 
00609   for (KateSuperRange* r = first(); r; r = next())
00610     if (r->includes(line))
00611       ret.append(r);
00612 
00613   return ret;
00614 }
00615 
00616 bool KateSuperRangeList::rangesInclude(const KateTextCursor& cursor)
00617 {
00618   for (KateSuperRange* r = first(); r; r = next())
00619     if (r->includes(cursor))
00620       return true;
00621 
00622   return false;
00623 }
00624 
00625 void KateSuperRangeList::slotEliminated()
00626 {
00627   if (sender()) {
00628     KateSuperRange* range = static_cast<KateSuperRange*>(const_cast<QObject*>(sender()));
00629     emit rangeEliminated(range);
00630 
00631     if (m_trackingBoundaries) {
00632       m_columnBoundaries.removeRef(range->m_start);
00633       m_columnBoundaries.removeRef(range->m_end);
00634     }
00635 
00636     if (m_autoManage)
00637       removeRef(range);
00638 
00639     if (!count())
00640       emit listEmpty();
00641   }
00642 }
00643 
00644 void KateSuperRangeList::slotDeleted(QObject* range)
00645 {
00646   KateSuperRange* r = static_cast<KateSuperRange*>(range);
00647 
00648   if (m_trackingBoundaries) {
00649       m_columnBoundaries.removeRef(r->m_start);
00650       m_columnBoundaries.removeRef(r->m_end);
00651   }
00652 
00653   int index = findRef(r);
00654   if (index != -1)
00655     take(index);
00656 
00657   if (!count())
00658       emit listEmpty();
00659 }
00660 
00661 KateSuperCursor* KateSuperRangeList::firstBoundary(const KateTextCursor* start)
00662 {
00663   if (!m_trackingBoundaries) {
00664     m_trackingBoundaries = true;
00665 
00666     for (KateSuperRange* r = first(); r; r = next()) {
00667       m_columnBoundaries.append(&(r->superStart()));
00668       m_columnBoundaries.append(&(r->superEnd()));
00669     }
00670   }
00671 
00672   m_columnBoundaries.sort();
00673 
00674   if (start)
00675     // OPTIMISE: QMap with QPtrList for each line? (==> sorting issues :( )
00676     for (KateSuperCursor* c = m_columnBoundaries.first(); c; c = m_columnBoundaries.next())
00677       if (*start <= *c)
00678         break;
00679 
00680   return m_columnBoundaries.current();
00681 }
00682 
00683 KateSuperCursor* KateSuperRangeList::nextBoundary()
00684 {
00685   KateSuperCursor* current = m_columnBoundaries.current();
00686 
00687   // make sure the new cursor is after the current cursor; multiple cursors with the same position can be in the list.
00688   if (current)
00689     while (m_columnBoundaries.next())
00690       if (*(m_columnBoundaries.current()) != *current)
00691         break;
00692 
00693   return m_columnBoundaries.current();
00694 }
00695 
00696 KateSuperCursor* KateSuperRangeList::currentBoundary()
00697 {
00698   return m_columnBoundaries.current();
00699 }
00700 
00701 int KateSuperRangeList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2)
00702 {
00703   if (static_cast<KateSuperRange*>(item1)->superStart() == static_cast<KateSuperRange*>(item2)->superStart()) {
00704     if (static_cast<KateSuperRange*>(item1)->superEnd() == static_cast<KateSuperRange*>(item2)->superEnd()) {
00705       return 0;
00706     } else {
00707       return static_cast<KateSuperRange*>(item1)->superEnd() < static_cast<KateSuperRange*>(item2)->superEnd() ? -1 : 1;
00708     }
00709   }
00710 
00711   return static_cast<KateSuperRange*>(item1)->superStart() < static_cast<KateSuperRange*>(item2)->superStart() ? -1 : 1;
00712 }
00713 
00714 QPtrCollection::Item KateSuperRangeList::newItem(QPtrCollection::Item d)
00715 {
00716   if (m_connect) {
00717     connect(static_cast<KateSuperRange*>(d), SIGNAL(destroyed(QObject*)), SLOT(slotDeleted(QObject*)));
00718     connect(static_cast<KateSuperRange*>(d), SIGNAL(eliminated()), SLOT(slotEliminated()));
00719     connect(static_cast<KateSuperRange*>(d), SIGNAL(tagRange(KateSuperRange*)), SIGNAL(tagRange(KateSuperRange*)));
00720 
00721     // HACK HACK
00722     static_cast<KateSuperRange*>(d)->slotTagRange();
00723   }
00724 
00725   if (m_trackingBoundaries) {
00726     m_columnBoundaries.append(&(static_cast<KateSuperRange*>(d)->superStart()));
00727     m_columnBoundaries.append(&(static_cast<KateSuperRange*>(d)->superEnd()));
00728   }
00729 
00730   return QPtrList<KateSuperRange>::newItem(d);
00731 }
00732 
00733 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Logo
This file is part of the documentation for kate Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Sep 30 05:22:39 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2003