File indexing completed on 2025-03-23 03:42:48
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 }