katesupercursor.cpp
/* This file is part of the KDE libraries
Copyright (C) 2003 Hamish Rodda <rodda@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "katesupercursor.h"
#include "katesupercursor.moc"
#include "katedocument.h"
#include <kdebug.h>
#include <qobjectlist.h>
KateSuperCursor::KateSuperCursor(KateDocument* doc, bool privateC, const KateTextCursor& cursor, QObject* parent, const char* name)
: QObject(parent, name)
, KateDocCursor(cursor.line(), cursor.col(), doc)
, Kate::Cursor ()
, m_doc (doc)
{
m_moveOnInsert = false;
m_lineRemoved = false;
m_privateCursor = privateC;
m_doc->addSuperCursor (this, privateC);
}
KateSuperCursor::KateSuperCursor(KateDocument* doc, bool privateC, int lineNum, int col, QObject* parent, const char* name)
: QObject(parent, name)
, KateDocCursor(lineNum, col, doc)
, Kate::Cursor ()
, m_doc (doc)
{
m_moveOnInsert = false;
m_lineRemoved = false;
m_privateCursor = privateC;
m_doc->addSuperCursor (this, privateC);
}
KateSuperCursor::~KateSuperCursor ()
{
m_doc->removeSuperCursor (this, m_privateCursor);
}
void KateSuperCursor::position(uint *pline, uint *pcol) const
{
KateDocCursor::position(pline, pcol);
}
bool KateSuperCursor::setPosition(uint line, uint col)
{
if (line == uint(-2) && col == uint(-2)) { delete this; return true; }
return KateDocCursor::setPosition(line, col);
}
bool KateSuperCursor::insertText(const QString& s)
{
return KateDocCursor::insertText(s);
}
bool KateSuperCursor::removeText(uint nbChar)
{
return KateDocCursor::removeText(nbChar);
}
QChar KateSuperCursor::currentChar() const
{
return KateDocCursor::currentChar();
}
bool KateSuperCursor::atStartOfLine() const
{
return col() == 0;
}
bool KateSuperCursor::atEndOfLine() const
{
return col() >= (int)m_doc->kateTextLine(line())->length();
}
bool KateSuperCursor::moveOnInsert() const
{
return m_moveOnInsert;
}
void KateSuperCursor::setMoveOnInsert(bool moveOnInsert)
{
m_moveOnInsert = moveOnInsert;
}
void KateSuperCursor::setLine(int lineNum)
{
int tempLine = line(), tempcol = col();
KateDocCursor::setLine(lineNum);
if (tempLine != line() || tempcol != col())
emit positionDirectlyChanged();
}
void KateSuperCursor::setCol(int colNum)
{
KateDocCursor::setCol(colNum);
}
void KateSuperCursor::setPos(const KateTextCursor& pos)
{
KateDocCursor::setPos(pos);
}
void KateSuperCursor::setPos(int lineNum, int colNum)
{
KateDocCursor::setPos(lineNum, colNum);
}
void KateSuperCursor::editTextInserted(uint line, uint col, uint len)
{
if (m_line == int(line))
{
if ((m_col > int(col)) || (m_moveOnInsert && (m_col == int(col))))
{
bool insertedAt = m_col == int(col);
m_col += len;
if (insertedAt)
emit charInsertedAt();
emit positionChanged();
return;
}
}
emit positionUnChanged();
}
void KateSuperCursor::editTextRemoved(uint line, uint col, uint len)
{
if (m_line == int(line))
{
if (m_col > int(col))
{
if (m_col > int(col + len))
{
m_col -= len;
}
else
{
bool prevCharDeleted = m_col == int(col + len);
m_col = col;
if (prevCharDeleted)
emit charDeletedBefore();
else
emit positionDeleted();
}
emit positionChanged();
return;
}
else if (m_col == int(col))
{
emit charDeletedAfter();
}
}
emit positionUnChanged();
}
void KateSuperCursor::editLineWrapped(uint line, uint col, bool newLine)
{
if (newLine)
{
if (m_line > int(line) || (m_line == int(line) && m_col >= int(col)))
{
if(m_line == int(line))
m_col -= col;
m_line++;
emit positionChanged();
return;
}
}
else if ( (m_line == int(line)) && (m_col > int(col)) || (m_moveOnInsert && (m_col == int(col))) )
{
m_line++;
m_col -= col;
emit positionChanged();
return;
}
emit positionUnChanged();
}
void KateSuperCursor::editLineUnWrapped(uint line, uint col, bool removeLine, uint length)
{
if (removeLine && (m_line > int(line+1)))
{
m_line--;
emit positionChanged();
return;
}
else if ( (m_line == int(line+1)) && (removeLine || (m_col < int(length))) )
{
m_line = line;
m_col += col;
emit positionChanged();
return;
}
else if ( (m_line == int(line+1)) && (m_col >= int(length)) )
{
m_col -= length;
emit positionChanged();
return;
}
emit positionUnChanged();
}
void KateSuperCursor::editLineInserted (uint line)
{
if (m_line >= int(line))
{
m_line++;
emit positionChanged();
return;
}
emit positionUnChanged();
}
void KateSuperCursor::editLineRemoved(uint line)
{
if (m_line > int(line))
{
m_line--;
emit positionChanged();
return;
}
else if (m_line == int(line))
{
m_line = (line <= m_doc->lastLine()) ? line : (line - 1);
m_col = 0;
emit positionDeleted();
emit positionChanged();
return;
}
emit positionUnChanged();
}
KateSuperCursor::operator QString()
{
return QString("[%1,%1]").arg(line()).arg(col());
}
KateSuperRange::KateSuperRange(KateSuperCursor* start, KateSuperCursor* end, QObject* parent, const char* name)
: QObject(parent, name)
, m_start(start)
, m_end(end)
, m_evaluate(false)
, m_startChanged(false)
, m_endChanged(false)
, m_deleteCursors(false)
, m_allowZeroLength(false)
{
init();
}
KateSuperRange::KateSuperRange(KateDocument* doc, const KateRange& range, QObject* parent, const char* name)
: QObject(parent, name)
, m_start(new KateSuperCursor(doc, true, range.start()))
, m_end(new KateSuperCursor(doc, true, range.end()))
, m_evaluate(false)
, m_startChanged(false)
, m_endChanged(false)
, m_deleteCursors(true)
, m_allowZeroLength(false)
{
init();
}
KateSuperRange::KateSuperRange(KateDocument* doc, const KateTextCursor& start, const KateTextCursor& end, QObject* parent, const char* name)
: QObject(parent, name)
, m_start(new KateSuperCursor(doc, true, start))
, m_end(new KateSuperCursor(doc, true, end))
, m_evaluate(false)
, m_startChanged(false)
, m_endChanged(false)
, m_deleteCursors(true)
, m_allowZeroLength(false)
{
init();
}
void KateSuperRange::init()
{
Q_ASSERT(isValid());
if (!isValid())
kdDebug(13020) << superStart() << " " << superEnd() << endl;
insertChild(m_start);
insertChild(m_end);
setBehaviour(DoNotExpand);
// Not necessarily the best implementation
connect(m_start, SIGNAL(positionDirectlyChanged()), SIGNAL(contentsChanged()));
connect(m_end, SIGNAL(positionDirectlyChanged()), SIGNAL(contentsChanged()));
connect(m_start, SIGNAL(positionChanged()), SLOT(slotEvaluateChanged()));
connect(m_end, SIGNAL(positionChanged()), SLOT(slotEvaluateChanged()));
connect(m_start, SIGNAL(positionUnChanged()), SLOT(slotEvaluateUnChanged()));
connect(m_end, SIGNAL(positionUnChanged()), SLOT(slotEvaluateUnChanged()));
connect(m_start, SIGNAL(positionDeleted()), SIGNAL(boundaryDeleted()));
connect(m_end, SIGNAL(positionDeleted()), SIGNAL(boundaryDeleted()));
}
KateSuperRange::~KateSuperRange()
{
if (m_deleteCursors)
{
//insertChild(m_start);
//insertChild(m_end);
delete m_start;
delete m_end;
}
}
KateTextCursor& KateSuperRange::start()
{
return *m_start;
}
const KateTextCursor& KateSuperRange::start() const
{
return *m_start;
}
KateTextCursor& KateSuperRange::end()
{
return *m_end;
}
const KateTextCursor& KateSuperRange::end() const
{
return *m_end;
}
KateSuperCursor& KateSuperRange::superStart()
{
return *m_start;
}
const KateSuperCursor& KateSuperRange::superStart() const
{
return *m_start;
}
KateSuperCursor& KateSuperRange::superEnd()
{
return *m_end;
}
const KateSuperCursor& KateSuperRange::superEnd() const
{
return *m_end;
}
int KateSuperRange::behaviour() const
{
return (m_start->moveOnInsert() ? DoNotExpand : ExpandLeft) | (m_end->moveOnInsert() ? ExpandRight : DoNotExpand);
}
void KateSuperRange::setBehaviour(int behaviour)
{
m_start->setMoveOnInsert(behaviour & ExpandLeft);
m_end->setMoveOnInsert(!(behaviour & ExpandRight));
}
bool KateSuperRange::isValid() const
{
return superStart() <= superEnd();
}
bool KateSuperRange::owns(const KateTextCursor& cursor) const
{
if (!includes(cursor)) return false;
if (children())
for (QObjectListIt it(*children()); *it; ++it)
if ((*it)->inherits("KateSuperRange"))
if (static_cast<KateSuperRange*>(*it)->owns(cursor))
return false;
return true;
}
bool KateSuperRange::includes(const KateTextCursor& cursor) const
{
return isValid() && cursor >= superStart() && cursor < superEnd();
}
bool KateSuperRange::includes(uint lineNum) const
{
return isValid() && (int)lineNum >= superStart().line() && (int)lineNum <= superEnd().line();
}
bool KateSuperRange::includesWholeLine(uint lineNum) const
{
return isValid() && ((int)lineNum > superStart().line() || ((int)lineNum == superStart().line() && superStart().atStartOfLine())) && ((int)lineNum < superEnd().line() || ((int)lineNum == superEnd().line() && superEnd().atEndOfLine()));
}
bool KateSuperRange::boundaryAt(const KateTextCursor& cursor) const
{
return isValid() && (cursor == superStart() || cursor == superEnd());
}
bool KateSuperRange::boundaryOn(uint lineNum) const
{
return isValid() && (superStart().line() == (int)lineNum || superEnd().line() == (int)lineNum);
}
void KateSuperRange::slotEvaluateChanged()
{
if (sender() == static_cast<QObject*>(m_start)) {
if (m_evaluate) {
if (!m_endChanged) {
// Only one was changed
evaluateEliminated();
} else {
// Both were changed
evaluatePositionChanged();
m_endChanged = false;
}
} else {
m_startChanged = true;
}
} else {
if (m_evaluate) {
if (!m_startChanged) {
// Only one was changed
evaluateEliminated();
} else {
// Both were changed
evaluatePositionChanged();
m_startChanged = false;
}
} else {
m_endChanged = true;
}
}
m_evaluate = !m_evaluate;
}
void KateSuperRange::slotEvaluateUnChanged()
{
if (sender() == static_cast<QObject*>(m_start)) {
if (m_evaluate) {
if (m_endChanged) {
// Only one changed
evaluateEliminated();
m_endChanged = false;
} else {
// Neither changed
emit positionUnChanged();
}
}
} else {
if (m_evaluate) {
if (m_startChanged) {
// Only one changed
evaluateEliminated();
m_startChanged = false;
} else {
// Neither changed
emit positionUnChanged();
}
}
}
m_evaluate = !m_evaluate;
}
void KateSuperRange::slotTagRange()
{
emit tagRange(this);
}
void KateSuperRange::evaluateEliminated()
{
if (superStart() == superEnd()) {
if (!m_allowZeroLength) emit eliminated();
}
else
emit contentsChanged();
}
void KateSuperRange::evaluatePositionChanged()
{
if (superStart() == superEnd())
emit eliminated();
else
emit positionChanged();
}
int KateSuperCursorList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2)
{
if (*(static_cast<KateSuperCursor*>(item1)) == *(static_cast<KateSuperCursor*>(item2)))
return 0;
return *(static_cast<KateSuperCursor*>(item1)) < *(static_cast<KateSuperCursor*>(item2)) ? -1 : 1;
}
KateSuperRangeList::KateSuperRangeList(bool autoManage, QObject* parent, const char* name)
: QObject(parent, name)
, m_autoManage(autoManage)
, m_connect(true)
, m_trackingBoundaries(false)
{
setAutoManage(autoManage);
}
KateSuperRangeList::KateSuperRangeList(const QPtrList<KateSuperRange>& rangeList, QObject* parent, const char* name)
: QObject(parent, name)
, m_autoManage(false)
, m_connect(false)
, m_trackingBoundaries(false)
{
appendList(rangeList);
}
void KateSuperRangeList::appendList(const QPtrList<KateSuperRange>& rangeList)
{
for (QPtrListIterator<KateSuperRange> it = rangeList; *it; ++it)
append(*it);
}
void KateSuperRangeList::clear()
{
for (KateSuperRange* range = first(); range; range = next())
emit rangeEliminated(range);
QPtrList<KateSuperRange>::clear();
}
void KateSuperRangeList::connectAll()
{
if (!m_connect) {
m_connect = true;
for (KateSuperRange* range = first(); range; range = next()) {
connect(range, SIGNAL(destroyed(QObject*)), SLOT(slotDeleted(QObject*)));
connect(range, SIGNAL(eliminated()), SLOT(slotEliminated()));
}
}
}
bool KateSuperRangeList::autoManage() const
{
return m_autoManage;
}
void KateSuperRangeList::setAutoManage(bool autoManage)
{
m_autoManage = autoManage;
setAutoDelete(m_autoManage);
}
QPtrList<KateSuperRange> KateSuperRangeList::rangesIncluding(const KateTextCursor& cursor)
{
sort();
QPtrList<KateSuperRange> ret;
for (KateSuperRange* r = first(); r; r = next())
if (r->includes(cursor))
ret.append(r);
return ret;
}
QPtrList<KateSuperRange> KateSuperRangeList::rangesIncluding(uint line)
{
sort();
QPtrList<KateSuperRange> ret;
for (KateSuperRange* r = first(); r; r = next())
if (r->includes(line))
ret.append(r);
return ret;
}
bool KateSuperRangeList::rangesInclude(const KateTextCursor& cursor)
{
for (KateSuperRange* r = first(); r; r = next())
if (r->includes(cursor))
return true;
return false;
}
void KateSuperRangeList::slotEliminated()
{
if (sender()) {
KateSuperRange* range = static_cast<KateSuperRange*>(const_cast<QObject*>(sender()));
emit rangeEliminated(range);
if (m_trackingBoundaries) {
m_columnBoundaries.removeRef(range->m_start);
m_columnBoundaries.removeRef(range->m_end);
}
if (m_autoManage)
removeRef(range);
if (!count())
emit listEmpty();
}
}
void KateSuperRangeList::slotDeleted(QObject* range)
{
//kdDebug(13020)<<"KateSuperRangeList::slotDeleted"<<endl;
KateSuperRange* r = static_cast<KateSuperRange*>(range);
if (m_trackingBoundaries) {
m_columnBoundaries.removeRef(r->m_start);
m_columnBoundaries.removeRef(r->m_end);
}
int index = findRef(r);
if (index != -1)
take(index);
//else kdDebug(13020)<<"Range not found in list"<<endl;
if (!count())
emit listEmpty();
}
KateSuperCursor* KateSuperRangeList::firstBoundary(const KateTextCursor* start)
{
if (!m_trackingBoundaries) {
m_trackingBoundaries = true;
for (KateSuperRange* r = first(); r; r = next()) {
m_columnBoundaries.append(&(r->superStart()));
m_columnBoundaries.append(&(r->superEnd()));
}
}
m_columnBoundaries.sort();
if (start)
// OPTIMISE: QMap with QPtrList for each line? (==> sorting issues :( )
for (KateSuperCursor* c = m_columnBoundaries.first(); c; c = m_columnBoundaries.next())
if (*start <= *c)
break;
return m_columnBoundaries.current();
}
KateSuperCursor* KateSuperRangeList::nextBoundary()
{
KateSuperCursor* current = m_columnBoundaries.current();
// make sure the new cursor is after the current cursor; multiple cursors with the same position can be in the list.
if (current)
while (m_columnBoundaries.next())
if (*(m_columnBoundaries.current()) != *current)
break;
return m_columnBoundaries.current();
}
KateSuperCursor* KateSuperRangeList::currentBoundary()
{
return m_columnBoundaries.current();
}
int KateSuperRangeList::compareItems(QPtrCollection::Item item1, QPtrCollection::Item item2)
{
if (static_cast<KateSuperRange*>(item1)->superStart() == static_cast<KateSuperRange*>(item2)->superStart()) {
if (static_cast<KateSuperRange*>(item1)->superEnd() == static_cast<KateSuperRange*>(item2)->superEnd()) {
return 0;
} else {
return static_cast<KateSuperRange*>(item1)->superEnd() < static_cast<KateSuperRange*>(item2)->superEnd() ? -1 : 1;
}
}
return static_cast<KateSuperRange*>(item1)->superStart() < static_cast<KateSuperRange*>(item2)->superStart() ? -1 : 1;
}
QPtrCollection::Item KateSuperRangeList::newItem(QPtrCollection::Item d)
{
if (m_connect) {
connect(static_cast<KateSuperRange*>(d), SIGNAL(destroyed(QObject*)), SLOT(slotDeleted(QObject*)));
connect(static_cast<KateSuperRange*>(d), SIGNAL(eliminated()), SLOT(slotEliminated()));
connect(static_cast<KateSuperRange*>(d), SIGNAL(tagRange(KateSuperRange*)), SIGNAL(tagRange(KateSuperRange*)));
// HACK HACK
static_cast<KateSuperRange*>(d)->slotTagRange();
}
if (m_trackingBoundaries) {
m_columnBoundaries.append(&(static_cast<KateSuperRange*>(d)->superStart()));
m_columnBoundaries.append(&(static_cast<KateSuperRange*>(d)->superEnd()));
}
return QPtrList<KateSuperRange>::newItem(d);
}
// kate: space-indent on; indent-width 2; replace-tabs on;
KStdAccel::next
const KShortcut & next()
KateTextCursor
Simple cursor class with no document pointer.
Definition: katecursor.h:33
KateDocCursor
Cursor class with a pointer to its document.
Definition: katecursor.h:92
KateSuperRange
Represents a range of text, from the start() to the end().
Definition: katesupercursor.h:168
KateSuperCursor::moveOnInsert
bool moveOnInsert() const
Returns how this cursor behaves when text is inserted at the cursor.
Definition: katesupercursor.cpp:95
KateSuperRange::isValid
virtual bool isValid() const
Start and end must be valid and start <= end.
Definition: katesupercursor.cpp:404
KateSuperRange::ExpandRight
Expand to encapsulate new characters to the right of the range.
Definition: katesupercursor.h:182
KateSuperRange::behaviour
int behaviour() const
Returns how this range reacts to characters inserted immediately outside the range.
Definition: katesupercursor.cpp:393
kdDebug
kdbgstream kdDebug(int area=0)
KateSuperCursor::charDeletedBefore
void charDeletedBefore()
The character immediately before the cursor was deleted.
KateSuperRange::includes
bool includes(const KateTextCursor &cursor) const
Returns true if the range includes cursor 's character.
Definition: katesupercursor.cpp:422
KateSuperRange::boundaryAt
bool boundaryAt(const KateTextCursor &cursor) const
Returns whether cursor is the site of a boundary of this range.
Definition: katesupercursor.cpp:437
KateSuperRange::DoNotExpand
Don't expand to encapsulate new characters in either direction. This is the default.
Definition: katesupercursor.h:178
KateSuperRange::boundaryOn
bool boundaryOn(uint lineNum) const
Returns whether there is a boundary of this range on line.
Definition: katesupercursor.cpp:442
KateSuperRange::boundaryDeleted
void boundaryDeleted()
Either cursor's surrounding characters were both deleted.
KateSuperCursor::positionUnChanged
void positionUnChanged()
Athough an edit took place, the cursor's position was unchanged.
KateSuperCursor::positionChanged
void positionChanged()
The cursor's position was changed.
KateSuperRange::contentsChanged
void contentsChanged()
The contents of the range changed.
KateSuperCursor::atEndOfLine
bool atEndOfLine() const
Definition: katesupercursor.cpp:90
KateSuperCursor::atStartOfLine
bool atStartOfLine() const
Definition: katesupercursor.cpp:85
KateSuperRange::superEnd
KateSuperCursor & superEnd()
Returns the super end cursor.
Definition: katesupercursor.cpp:383
KateSuperRange::KateSuperRange
KateSuperRange(KateSuperCursor *start, KateSuperCursor *end, QObject *parent=0L, const char *name=0L)
Constructor.
Definition: katesupercursor.cpp:280
KateSuperRange::positionUnChanged
void positionUnChanged()
The range's position was unchanged.
KateSuperCursor::positionDirectlyChanged
void positionDirectlyChanged()
The cursor's position was directly changed by the program.
KateSuperCursor::charDeletedAfter
void charDeletedAfter()
The character immediately after the cursor was deleted.
KateSuperRange::positionChanged
void positionChanged()
More interesting signals that aren't worth implementing here: firstCharDeleted: start()::charDeleted(...
KateSuperRange::owns
bool owns(const KateTextCursor &cursor) const
This is for use where the ranges are used in a heirachy, ie.
Definition: katesupercursor.cpp:409
KateSuperCursor
Possible additional features:
Definition: katesupercursor.h:45
KateSuperCursor::charInsertedAt
void charInsertedAt()
A character was inserted immediately before the cursor.
KateSuperRange::ExpandLeft
Expand to encapsulate new characters to the left of the range.
Definition: katesupercursor.h:180
KateSuperCursor::KateSuperCursor
KateSuperCursor(KateDocument *doc, bool privateC, const KateTextCursor &cursor, QObject *parent=0L, const char *name=0L)
bool privateC says: if private, than don't show to apps using the cursorinterface in the list...
Definition: katesupercursor.cpp:28
KateSuperRange::includesWholeLine
bool includesWholeLine(uint lineNum) const
Returns true if the range totally encompasses line.
Definition: katesupercursor.cpp:432
KateSuperCursor::positionDeleted
void positionDeleted()
The cursor's surrounding characters were both deleted simultaneously.
endl
kndbgstream & endl(kndbgstream &s)
KateSuperRange::superStart
KateSuperCursor & superStart()
Returns the super start cursor.
Definition: katesupercursor.cpp:373
KateSuperRange::tagRange
void tagRange(KateSuperRange *range)
Indicates the region needs re-drawing.
KateSuperCursor::setMoveOnInsert
void setMoveOnInsert(bool moveOnInsert)
Change the behavior of the cursor when text is inserted at the cursor.
Definition: katesupercursor.cpp:100
KateSuperRange::eliminated
void eliminated()
The range now contains no characters (ie.
KateSuperRange::setBehaviour
void setBehaviour(int behaviour)
Determine how the range should react to characters inserted immediately outside the range...
Definition: katesupercursor.cpp:398

KDE Home | KDE Accessibility Home | Description of Access Keys