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
43void TextCursor::setPosition(const TextCursor &position)
44{
45 if (m_block && m_block != position.m_block) {
46 m_block->removeCursor(cursor: this);
47 }
48
49 m_line = position.m_line;
50 m_column = position.m_column;
51
52 m_block = position.m_block;
53 if (m_block) {
54 m_block->insertCursor(cursor: this);
55 }
56}
57
58void TextCursor::setPosition(KTextEditor::Cursor position, bool init)
59{
60 // any change or init? else do nothing
61 if (!init && position.line() == line()) {
62 // simple case: 1:1 equal
63 if (position.column() == m_column) {
64 return;
65 }
66
67 // ok, too: both old and new column are valid, we can just adjust the column and be done
68 if (position.column() >= 0 && m_column >= 0) {
69 m_column = position.column();
70 return;
71 }
72
73 // else: we need to handle the change in a more complex way, new or old column are not valid!
74 }
75
76 // first: validate the line and column, else invalid
77 if (!position.isValid() || position.line() >= m_buffer->lines()) {
78 if (m_block) {
79 m_block->removeCursor(cursor: this);
80 }
81 m_block = nullptr;
82 m_line = m_column = -1;
83 return;
84 }
85
86 // find new block if m_block doesn't contain the line or if the block is null
87 TextBlock *oldBlock = m_block;
88 int startLine = oldBlock ? oldBlock->startLine() : -1;
89 if (!oldBlock || position.line() < startLine || position.line() >= startLine + oldBlock->lines()) {
90 if (oldBlock) {
91 oldBlock->removeCursor(cursor: this);
92 }
93 m_block = m_buffer->m_blocks[m_buffer->blockForLine(line: position.line())];
94 Q_ASSERT(m_block);
95 m_block->insertCursor(cursor: this);
96 startLine = m_block->startLine();
97 }
98
99 // else: valid cursor
100 m_line = position.line() - startLine;
101 m_column = position.column();
102}
103
104KTextEditor::Document *Kate::TextCursor::document() const
105{
106 return m_buffer->document();
107}
108
109KTextEditor::MovingRange *Kate::TextCursor::range() const
110{
111 return m_range;
112}
113
114void Kate::TextCursor::setPosition(KTextEditor::Cursor position)
115{
116 setPosition(position, init: false);
117}
118
119void Kate::TextCursor::setPosition(int line, int column)
120{
121 setPosition(position: KTextEditor::Cursor(line, column), init: false);
122}
123}
124

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