File indexing completed on 2024-07-14 03:55:46

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 "katetextblock.h"
0013 #include "katetextbuffer.h"
0014 #include "katetextrange.h"
0015 
0016 namespace Kate
0017 {
0018 TextCursor::TextCursor(TextBuffer &buffer, const KTextEditor::Cursor position, InsertBehavior insertBehavior)
0019     : m_buffer(buffer)
0020     , m_moveOnInsert(insertBehavior == MoveOnInsert)
0021 {
0022     // init position
0023     setPosition(position, true);
0024 }
0025 
0026 TextCursor::TextCursor(TextBuffer &buffer, TextRange *range, KTextEditor::Cursor position, InsertBehavior insertBehavior)
0027     : m_buffer(buffer)
0028     , m_range(range)
0029     , m_moveOnInsert(insertBehavior == MoveOnInsert)
0030 {
0031     // init position
0032     setPosition(position, true);
0033 }
0034 
0035 TextCursor::~TextCursor()
0036 {
0037     // remove cursor from block or buffer
0038     if (m_block) {
0039         m_block->removeCursor(this);
0040     }
0041 
0042     // only cursors without range are here!
0043     else if (!m_range) {
0044         m_buffer.m_invalidCursors.remove(this);
0045     }
0046 }
0047 
0048 void TextCursor::setPosition(const TextCursor &position)
0049 {
0050     if (m_block && m_block != position.m_block) {
0051         m_block->removeCursor(this);
0052     }
0053 
0054     m_line = position.m_line;
0055     m_column = position.m_column;
0056 
0057     m_block = position.m_block;
0058     if (m_block) {
0059         m_block->insertCursor(this);
0060     }
0061 }
0062 
0063 void TextCursor::setPosition(KTextEditor::Cursor position, bool init)
0064 {
0065     // any change or init? else do nothing
0066     if (!init && position.line() == line()) {
0067         // simple case: 1:1 equal
0068         if (position.column() == m_column) {
0069             return;
0070         }
0071 
0072         // ok, too: both old and new column are valid, we can just adjust the column and be done
0073         if (position.column() >= 0 && m_column >= 0) {
0074             m_column = position.column();
0075             return;
0076         }
0077 
0078         // else: we need to handle the change in a more complex way, new or old column are not valid!
0079     }
0080 
0081     // first: validate the line and column, else invalid
0082     if (!position.isValid() || position.line() >= m_buffer.lines()) {
0083         if (!m_range) {
0084             m_buffer.m_invalidCursors.insert(this);
0085         }
0086         if (m_block) {
0087             m_block->removeCursor(this);
0088         }
0089         m_block = nullptr;
0090         m_line = m_column = -1;
0091         return;
0092     }
0093 
0094     // find new block if m_block doesn't contain the line or if the block is null
0095     TextBlock *oldBlock = m_block;
0096     int startLine = oldBlock ? oldBlock->startLine() : -1;
0097     if (!oldBlock || position.line() < startLine || position.line() >= startLine + oldBlock->lines()) {
0098         if (oldBlock) {
0099             oldBlock->removeCursor(this);
0100         }
0101         m_block = m_buffer.m_blocks[m_buffer.blockForLine(position.line())];
0102         Q_ASSERT(m_block);
0103         m_block->insertCursor(this);
0104         startLine = m_block->startLine();
0105     }
0106 
0107     // if cursor was invalid before, remove it from invalid cursor list
0108     if (!m_range && !oldBlock && !init) {
0109         Q_ASSERT(m_buffer.m_invalidCursors.contains(this));
0110         m_buffer.m_invalidCursors.remove(this);
0111     }
0112 
0113     // else: valid cursor
0114     m_line = position.line() - startLine;
0115     m_column = position.column();
0116 }
0117 
0118 KTextEditor::Document *Kate::TextCursor::document() const
0119 {
0120     return m_buffer.document();
0121 }
0122 
0123 KTextEditor::MovingRange *Kate::TextCursor::range() const
0124 {
0125     return m_range;
0126 }
0127 
0128 void Kate::TextCursor::setPosition(KTextEditor::Cursor position)
0129 {
0130     setPosition(position, false);
0131 }
0132 
0133 void Kate::TextCursor::setPosition(int line, int column)
0134 {
0135     setPosition(KTextEditor::Cursor(line, column), false);
0136 }
0137 }