File indexing completed on 2024-04-21 15:03:33

0001 /*
0002     SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org>
0003 
0004     Based on code of the SmartCursor/Range by:
0005     SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #include "katetextcursor.h"
0011 #include "katedocument.h"
0012 #include "katetextbuffer.h"
0013 #include "katetextrange.h"
0014 
0015 namespace Kate
0016 {
0017 TextCursor::TextCursor(TextBuffer &buffer, const KTextEditor::Cursor position, InsertBehavior insertBehavior)
0018     : m_buffer(buffer)
0019     , m_range(nullptr)
0020     , m_block(nullptr)
0021     , m_line(-1)
0022     , m_column(-1)
0023     , m_moveOnInsert(insertBehavior == MoveOnInsert)
0024 {
0025     // init position
0026     setPosition(position, true);
0027 }
0028 
0029 TextCursor::TextCursor(TextBuffer &buffer, TextRange *range, const KTextEditor::Cursor position, InsertBehavior insertBehavior)
0030     : m_buffer(buffer)
0031     , m_range(range)
0032     , m_block(nullptr)
0033     , m_line(-1)
0034     , m_column(-1)
0035     , m_moveOnInsert(insertBehavior == MoveOnInsert)
0036 {
0037     // init position
0038     setPosition(position, true);
0039 }
0040 
0041 TextCursor::~TextCursor()
0042 {
0043     // remove cursor from block or buffer
0044     if (m_block) {
0045         m_block->removeCursor(this);
0046     }
0047 
0048     // only cursors without range are here!
0049     else if (!m_range) {
0050         m_buffer.m_invalidCursors.remove(this);
0051     }
0052 }
0053 
0054 void TextCursor::setPosition(const TextCursor &position)
0055 {
0056     if (m_block && m_block != position.m_block) {
0057         m_block->removeCursor(this);
0058     }
0059 
0060     m_line = position.m_line;
0061     m_column = position.m_column;
0062 
0063     m_block = position.m_block;
0064     if (m_block) {
0065         m_block->insertCursor(this);
0066     }
0067 }
0068 
0069 void TextCursor::setPosition(const KTextEditor::Cursor &position, bool init)
0070 {
0071     // any change or init? else do nothing
0072     if (!init && position.line() == line()) {
0073         // simple case: 1:1 equal
0074         if (position.column() == m_column) {
0075             return;
0076         }
0077 
0078         // ok, too: both old and new column are valid, we can just adjust the column and be done
0079         if (position.column() >= 0 && m_column >= 0) {
0080             m_column = position.column();
0081             return;
0082         }
0083 
0084         // else: we need to handle the change in a more complex way, new or old column are not valid!
0085     }
0086 
0087     // remove cursor from old block in any case
0088     if (m_block) {
0089         m_block->removeCursor(this);
0090     }
0091 
0092     // first: validate the line and column, else invalid
0093     if (position.column() < 0 || position.line() < 0 || position.line() >= m_buffer.lines()) {
0094         if (!m_range) {
0095             m_buffer.m_invalidCursors.insert(this);
0096         }
0097         m_block = nullptr;
0098         m_line = m_column = -1;
0099         return;
0100     }
0101 
0102     // else, find block
0103     TextBlock *block = m_buffer.blockForIndex(m_buffer.blockForLine(position.line()));
0104     Q_ASSERT(block);
0105 
0106     // if cursor was invalid before, remove it from invalid cursor list
0107     if (!m_range && !m_block && !init) {
0108         Q_ASSERT(m_buffer.m_invalidCursors.contains(this));
0109         m_buffer.m_invalidCursors.remove(this);
0110     }
0111 
0112     // else: valid cursor
0113     m_block = block;
0114     m_line = position.line() - m_block->startLine();
0115     m_column = position.column();
0116     m_block->insertCursor(this);
0117 }
0118 
0119 void TextCursor::setPosition(const KTextEditor::Cursor &position)
0120 {
0121     setPosition(position, false);
0122 }
0123 
0124 int TextCursor::line() const
0125 {
0126     // invalid cursor have no block
0127     if (!m_block) {
0128         return -1;
0129     }
0130 
0131     // else, calculate real line
0132     return m_block->startLine() + m_line;
0133 }
0134 
0135 KTextEditor::Document *Kate::TextCursor::document() const
0136 {
0137     return m_buffer.document();
0138 }
0139 
0140 KTextEditor::MovingRange *Kate::TextCursor::range() const
0141 {
0142     return m_range;
0143 }
0144 
0145 }