21 #include "katetextblock.h" 22 #include "katetextbuffer.h" 24 #include <QVarLengthArray> 30 , m_startLine(startLine)
33 m_lines.reserve(m_buffer->m_blockSize);
39 Q_ASSERT(m_lines.empty());
40 Q_ASSERT(m_cursors.empty());
48 Q_ASSERT(startLine >= 0);
49 Q_ASSERT(startLine < m_buffer->
lines());
76 for (
size_t i = 0; i < m_lines.size(); ++i) {
82 text.
append(m_lines.at(i)->text());
95 Q_ASSERT(position.
column() >= 0);
105 if (position.
column() > 0 || text.
size() == 0 || m_lines.at(line)->markedAsModified()) {
106 m_lines.at(line + 1)->markAsModified(
true);
107 }
else if (m_lines.at(line)->markedAsSavedOnDisk()) {
108 m_lines.at(line + 1)->markAsSavedOnDisk(
true);
114 m_lines.at(line + 1)->textReadWrite() = text.
right(text.
size() - position.
column());
120 m_lines.at(line)->markAsModified(
true);
128 m_buffer->fixStartLines(fixStartLinesStartIndex);
133 m_buffer->
history().wrapLine(position);
142 if (m_cursors.empty()) {
151 if (cursor->lineInBlock() <
line) {
156 if (cursor->lineInBlock() >
line) {
164 if (cursor->column() <= position.
column()) {
165 if (cursor->column() < position.
column() || !cursor->m_moveOnInsert) {
176 cursor->m_column -= position.
column();
180 auto range = cursor->kateRange();
181 if (range && !range->isValidityCheckRequired()) {
182 range->setValidityCheckRequired();
189 for (
TextRange *range : qAsConst(changedRanges)) {
190 range->checkValidity();
202 Q_ASSERT(previousBlock);
203 Q_ASSERT(previousBlock->
lines() > 0);
207 int lastLineOfPreviousBlock = previousBlock->
lines() - 1;
208 TextLine newFirst = previousBlock->m_lines.back();
209 m_lines[0] = newFirst;
210 previousBlock->m_lines.erase(previousBlock->m_lines.begin() + (previousBlock->
lines() - 1));
212 const int oldSizeOfPreviousLine = newFirst->text().size();
213 if (oldFirst->length() > 0) {
215 newFirst->textReadWrite().append(oldFirst->text());
218 newFirst->markAsModified(
true);
229 m_buffer->fixStartLines(fixStartLinesStartIndex);
241 if (m_cursors.empty() && previousBlock->m_cursors.empty()) {
250 if (cursor->lineInBlock() == 0) {
252 cursor->m_column += oldSizeOfPreviousLine;
255 auto range = cursor->kateRange();
256 if (range && !range->isValidityCheckRequired()) {
257 range->setValidityCheckRequired();
264 for (
auto it = previousBlock->m_cursors.begin(); it != previousBlock->m_cursors.end();) {
266 if (cursor->lineInBlock() == lastLineOfPreviousBlock) {
268 cursor->m_block =
this;
269 m_cursors.insert(cursor);
272 auto range = cursor->kateRange();
273 if (range && !range->isValidityCheckRequired()) {
274 range->setValidityCheckRequired();
279 it = previousBlock->m_cursors.erase(it);
289 for (
TextRange *range : qAsConst(changedRanges)) {
295 range->checkValidity();
303 const int oldSizeOfPreviousLine = m_lines.at(line - 1)->length();
304 const int sizeOfCurrentLine = m_lines.at(line)->length();
305 if (sizeOfCurrentLine > 0) {
306 m_lines.at(line - 1)->textReadWrite().append(m_lines.at(line)->text());
309 const bool lineChanged = (oldSizeOfPreviousLine > 0 && m_lines.at(line - 1)->markedAsModified()) || (sizeOfCurrentLine > 0 && (oldSizeOfPreviousLine > 0 || m_lines.at(line)->markedAsModified()));
310 m_lines.at(line - 1)->markAsModified(lineChanged);
311 if (oldSizeOfPreviousLine == 0 && m_lines.at(line)->markedAsSavedOnDisk()) {
312 m_lines.at(line - 1)->markAsSavedOnDisk(
true);
315 m_lines.erase(m_lines.begin() +
line);
322 m_buffer->fixStartLines(fixStartLinesStartIndex);
334 if (m_cursors.empty()) {
343 if (cursor->lineInBlock() <
line) {
348 if (cursor->lineInBlock() ==
line) {
350 cursor->m_column += oldSizeOfPreviousLine;
357 auto range = cursor->kateRange();
358 if (range && !range->isValidityCheckRequired()) {
359 range->setValidityCheckRequired();
366 for (
TextRange *range : qAsConst(changedRanges)) {
367 range->checkValidity();
377 QString &textOfLine = m_lines.at(line)->textReadWrite();
378 int oldLength = textOfLine.
size();
379 m_lines.at(line)->markAsModified(
true);
382 Q_ASSERT(position.
column() >= 0);
383 Q_ASSERT(position.
column() <= textOfLine.
size());
391 m_buffer->
history().insertText(position, text.
size(), oldLength);
398 if (m_cursors.empty()) {
407 if (cursor->lineInBlock() !=
line) {
412 if (cursor->column() <= position.
column()) {
413 if (cursor->column() < position.
column() || !cursor->m_moveOnInsert) {
419 if (cursor->m_column <= oldLength) {
420 cursor->m_column += text.
size();
424 else if (cursor->m_column < textOfLine.
size()) {
425 cursor->m_column = textOfLine.
size();
430 auto range = cursor->kateRange();
431 if (range && !range->isValidityCheckRequired() && (range->feedback() || range->start().line() == range->end().line())) {
432 range->setValidityCheckRequired();
439 for (
TextRange *range : qAsConst(changedRanges)) {
440 range->checkValidity();
450 QString &textOfLine = m_lines.at(line)->textReadWrite();
451 int oldLength = textOfLine.
size();
464 m_lines.at(line)->markAsModified(
true);
469 m_buffer->
history().removeText(range, oldLength);
476 if (m_cursors.empty()) {
485 if (cursor->lineInBlock() !=
line) {
495 if (cursor->column() <= range.
end().
column()) {
503 auto range = cursor->kateRange();
504 if (range && !range->isValidityCheckRequired() && (range->feedback() || range->
start().
line() == range->
end().
line())) {
505 range->setValidityCheckRequired();
512 for (
TextRange *range : qAsConst(changedRanges)) {
513 range->checkValidity();
520 for (
size_t i = 0; i < m_lines.size(); ++i)
521 printf(
"%4d - %4lld : %4d : '%s'\n", blockIndex, (
unsigned long long)
startLine() + i, m_lines.at(i)->text().size(), qPrintable(m_lines.at(i)->text()));
527 int linesOfNewBlock =
lines() - fromLine;
533 newBlock->m_lines.reserve(linesOfNewBlock);
534 for (
size_t i = fromLine; i < m_lines.size(); ++i) {
535 newBlock->m_lines.push_back(m_lines.at(i));
537 m_lines.resize(fromLine);
540 for (
auto it = m_cursors.begin(); it != m_cursors.end();) {
542 if (cursor->lineInBlock() >= fromLine) {
543 cursor->m_line = cursor->lineInBlock() - fromLine;
544 cursor->m_block = newBlock;
547 newBlock->m_cursors.insert(cursor);
548 it = m_cursors.erase(it);
556 const QList<TextRange *> allRanges = m_uncachedRanges.toList() + m_cachedLineForRanges.keys();
557 for (
TextRange *range : qAsConst(allRanges)) {
571 cursor->m_line = cursor->lineInBlock() + targetBlock->
lines();
572 cursor->m_block = targetBlock;
573 targetBlock->m_cursors.insert(cursor);
578 targetBlock->m_lines.reserve(targetBlock->
lines() +
lines());
579 for (
size_t i = 0; i < m_lines.size(); ++i) {
580 targetBlock->m_lines.push_back(m_lines.at(i));
585 const QList<TextRange *> allRanges = m_uncachedRanges.toList() + m_cachedLineForRanges.keys();
586 for (
TextRange *range : qAsConst(allRanges)) {
598 for (
auto it = m_cursors.begin(); it != m_cursors.end();) {
600 if (!cursor->kateRange()) {
602 it = m_cursors.erase(it);
621 for (
auto it = m_cursors.begin(); it != m_cursors.end();) {
623 if (!cursor->kateRange()) {
624 cursor->m_column = 0;
626 cursor->m_block = targetBlock;
627 targetBlock->m_cursors.insert(cursor);
630 it = m_cursors.erase(it);
644 for (
auto &textLine : m_lines) {
645 if (textLine->markedAsModified()) {
646 textLine->markAsSavedOnDisk(
true);
658 const bool isSingleLine = startLine == endLine;
663 if ((endLine < m_startLine) || (startLine >= (m_startLine +
lines()))) {
671 if (isSingleLine && m_cachedLineForRanges.contains(range) && (m_cachedLineForRanges.value(range) == startLine - m_startLine)) {
678 if (!isSingleLine && m_uncachedRanges.contains(range)) {
694 m_uncachedRanges.insert(range);
701 const int lineOffset = startLine - m_startLine;
706 if (m_cachedRangesForLine.size() <= lineOffset) {
707 m_cachedRangesForLine.resize(lineOffset + 1);
713 m_cachedRangesForLine[lineOffset].insert(range);
714 m_cachedLineForRanges[range] = lineOffset;
722 if (m_uncachedRanges.remove(range)) {
726 Q_ASSERT(!m_cachedLineForRanges.contains(range));
734 if (it != m_cachedLineForRanges.end()) {
738 Q_ASSERT(!m_uncachedRanges.contains(range));
743 Q_ASSERT(m_cachedRangesForLine.at(*it).contains(range));
748 m_cachedRangesForLine[*it].remove(range);
749 m_cachedLineForRanges.erase(it);
QString & append(QChar ch)
void wrapLine(const KTextEditor::Cursor &position, int fixStartLinesStartIndex)
Wrap line at given cursor position.
QSharedPointer< T > create()
void setStartLine(int startLine)
Set start line of this block.
void removeRange(TextRange *range)
Remove a range from this block.
void unwrapLine(int line, TextBlock *previousBlock, int fixStartLinesStartIndex)
Unwrap given line.
int lines() const
Number of lines in this block.
void push_back(const T &t)
QString & remove(int position, int n)
int lineInternal() const
Non-virtual version of line(), which is faster.
The Cursor represents a position in a Document.
int startLine() const
Start line of this block.
Class representing a single text line.
void deleteBlockContent()
Delete the block content, delete all lines and delete all cursors not bound to ranges.
void debugPrint(int blockIndex) const
Debug output, print whole block content with line numbers and line length.
TextBlock(TextBuffer *buffer, int startLine)
Construct an empty text block.
~TextBlock()
Destruct the text block.
void updateRange(TextRange *range)
Update a range from this block.
void clearBlockContent(TextBlock *targetBlock)
Clear the block content, delete all lines, move all cursors not bound to range to given block at 0...
QString & insert(int position, QChar ch)
void markModifiedLinesAsSaved()
Flag all modified text lines as saved on disk.
constexpr int column() const Q_DECL_NOEXCEPT
Retrieve the column on which this cursor is situated.
constexpr Cursor start() const Q_DECL_NOEXCEPT
Get the start position of this range.
void removeText(const KTextEditor::Range &range, QString &removedText)
Remove text at given range.
QString right(int n) const
An object representing a section of text, from one Cursor to another.
void appendLine(const QString &textOfLine)
Append a new line with given text.
void clearLines()
Clear the lines.
QString mid(int position, int n) const
void mergeBlock(TextBlock *targetBlock)
Merge this block with given one, the given one must be a direct predecessor.
Class representing a 'clever' text cursor.
constexpr Cursor end() const Q_DECL_NOEXCEPT
Get the end position of this range.
constexpr int line() const Q_DECL_NOEXCEPT
Retrieve the line on which this cursor is situated.
TextLine line(int line) const
Retrieve a text line.
Class representing a text buffer.
TextHistory & history()
TextHistory of this buffer.
void text(QString &text) const
Retrieve text of block.
void insertText(const KTextEditor::Cursor &position, const QString &text)
Insert text at given cursor position.
Class representing a text block.
TextBlock * splitBlock(int fromLine)
Split given block.