1/*
2 SPDX-FileCopyrightText: 2010 Christoph Cullmann <cullmann@kde.org>
3
4 Based on code of the SmartCursor/Range by:
5 SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "katetextcursor.h"
11#include "katedocument.h"
12#include "katetextblock.h"
13#include "katetextbuffer.h"
14#include "katetextrange.h"
15
16namespace Kate
17{
18TextCursor::TextCursor(TextBuffer &buffer, const KTextEditor::Cursor position, InsertBehavior insertBehavior)
19 : m_buffer(buffer)
20 , m_moveOnInsert(insertBehavior == MoveOnInsert)
21{
22 // init position
23 setPosition(position, init: true);
24}
25
26TextCursor::TextCursor(TextBuffer &buffer, TextRange *range, KTextEditor::Cursor position, InsertBehavior insertBehavior)
27 : m_buffer(buffer)
28 , m_range(range)
29 , m_moveOnInsert(insertBehavior == MoveOnInsert)
30{
31 // init position
32 setPosition(position, init: true);
33}
34
35TextCursor::~TextCursor()
36{
37 // remove cursor from block or buffer
38 if (m_block) {
39 m_block->removeCursor(cursor: this);
40 }
41
42 // only cursors without range are here!
43 else if (!m_range) {
44 m_buffer.m_invalidCursors.remove(value: this);
45 }
46}
47
48void TextCursor::setPosition(const TextCursor &position)
49{
50 if (m_block && m_block != position.m_block) {
51 m_block->removeCursor(cursor: this);
52 }
53
54 m_line = position.m_line;
55 m_column = position.m_column;
56
57 m_block = position.m_block;
58 if (m_block) {
59 m_block->insertCursor(cursor: this);
60 }
61}
62
63void TextCursor::setPosition(KTextEditor::Cursor position, bool init)
64{
65 // any change or init? else do nothing
66 if (!init && position.line() == line()) {
67 // simple case: 1:1 equal
68 if (position.column() == m_column) {
69 return;
70 }
71
72 // ok, too: both old and new column are valid, we can just adjust the column and be done
73 if (position.column() >= 0 && m_column >= 0) {
74 m_column = position.column();
75 return;
76 }
77
78 // else: we need to handle the change in a more complex way, new or old column are not valid!
79 }
80
81 // first: validate the line and column, else invalid
82 if (!position.isValid() || position.line() >= m_buffer.lines()) {
83 if (!m_range) {
84 m_buffer.m_invalidCursors.insert(value: this);
85 }
86 if (m_block) {
87 m_block->removeCursor(cursor: this);
88 }
89 m_block = nullptr;
90 m_line = m_column = -1;
91 return;
92 }
93
94 // find new block if m_block doesn't contain the line or if the block is null
95 TextBlock *oldBlock = m_block;
96 int startLine = oldBlock ? oldBlock->startLine() : -1;
97 if (!oldBlock || position.line() < startLine || position.line() >= startLine + oldBlock->lines()) {
98 if (oldBlock) {
99 oldBlock->removeCursor(cursor: this);
100 }
101 m_block = m_buffer.m_blocks[m_buffer.blockForLine(line: position.line())];
102 Q_ASSERT(m_block);
103 m_block->insertCursor(cursor: this);
104 startLine = m_block->startLine();
105 }
106
107 // if cursor was invalid before, remove it from invalid cursor list
108 if (!m_range && !oldBlock && !init) {
109 Q_ASSERT(m_buffer.m_invalidCursors.contains(this));
110 m_buffer.m_invalidCursors.remove(value: this);
111 }
112
113 // else: valid cursor
114 m_line = position.line() - startLine;
115 m_column = position.column();
116}
117
118KTextEditor::Document *Kate::TextCursor::document() const
119{
120 return m_buffer.document();
121}
122
123KTextEditor::MovingRange *Kate::TextCursor::range() const
124{
125 return m_range;
126}
127
128void Kate::TextCursor::setPosition(KTextEditor::Cursor position)
129{
130 setPosition(position, init: false);
131}
132
133void Kate::TextCursor::setPosition(int line, int column)
134{
135 setPosition(position: KTextEditor::Cursor(line, column), init: false);
136}
137}
138

source code of ktexteditor/src/buffer/katetextcursor.cpp