Index: src/document/katedocument.cpp =================================================================== --- src/document/katedocument.cpp +++ src/document/katedocument.cpp @@ -2974,130 +2974,131 @@ } } + editStart(); + /** - * selection around => special handling if we want to add auto brackets + * special handling if we want to add auto brackets to a selection */ if (view->selection() && !closingBracket.isNull()) { - /** - * add bracket at start + end of the selection - */ - KTextEditor::Cursor oldCur = view->cursorPosition(); - insertText(view->selectionRange().start(), chars); - view->slotTextInserted(view, oldCur, chars); + std::unique_ptr selectionRange(newMovingRange(view->selectionRange())); + const int startLine = qMax(0, selectionRange->start().line()); + const int endLine = qMin(selectionRange->end().line(), lastLine()); + const bool blockMode = view->blockSelection() && (startLine != endLine); + if (blockMode) { + // Add brackets to each line of the block + const KTextEditor::Range workingRange = view->selectionRange(); + for (int line = startLine; line <= endLine; ++line) { + const KTextEditor::Range r(rangeOnLine(workingRange, line)); + insertText(r.end(), QString(closingBracket)); + insertText(r.start(), chars); + } + } else { + // No block, just add to start & end of selection + insertText(selectionRange->end(), QString(closingBracket)); + insertText(selectionRange->start(), chars); + } - view->setCursorPosition(view->selectionRange().end()); - oldCur = view->cursorPosition(); - insertText(view->selectionRange().end(), QString(closingBracket)); - view->slotTextInserted(view, oldCur, QString(closingBracket)); + // Refesh selection + view->setSelection(selectionRange->toRange()); + view->setCursorPosition(selectionRange->end()); - /** - * expand selection - */ - view->setSelection(KTextEditor::Range(view->selectionRange().start() + Cursor{0, 1}, - view->cursorPosition() - Cursor{0, 1})); - view->setCursorPosition(view->selectionRange().start()); + editEnd(); + return true; } /** - * else normal handling + * normal handling */ - else { - editStart(); + if (!view->config()->persistentSelection() && view->selection()) { + view->removeSelectedText(); + } - if (!view->config()->persistentSelection() && view->selection()) { - view->removeSelectedText(); - } + const KTextEditor::Cursor oldCur(view->cursorPosition()); - const KTextEditor::Cursor oldCur(view->cursorPosition()); - - const bool multiLineBlockMode = view->blockSelection() && view->selection(); - if (view->currentInputMode()->overwrite()) { - // blockmode multiline selection case: remove chars in every line - const KTextEditor::Range selectionRange = view->selectionRange(); - const int startLine = multiLineBlockMode ? qMax(0, selectionRange.start().line()) : view->cursorPosition().line(); - const int endLine = multiLineBlockMode ? qMin(selectionRange.end().line(), lastLine()) : startLine; - const int virtualColumn = toVirtualColumn(multiLineBlockMode ? selectionRange.end() : view->cursorPosition()); - - for (int line = endLine; line >= startLine; --line) { - Kate::TextLine textLine = m_buffer->plainLine(line); - Q_ASSERT(textLine); - const int column = fromVirtualColumn(line, virtualColumn); - KTextEditor::Range r = KTextEditor::Range(KTextEditor::Cursor(line, column), qMin(chars.length(), - textLine->length() - column)); - - // replace mode needs to know what was removed so it can be restored with backspace - if (oldCur.column() < lineLength(line)) { - QChar removed = characterAt(KTextEditor::Cursor(line, column)); - view->currentInputMode()->overwrittenChar(removed); - } + const bool multiLineBlockMode = view->blockSelection() && view->selection(); + if (view->currentInputMode()->overwrite()) { + // blockmode multiline selection case: remove chars in every line + const KTextEditor::Range selectionRange = view->selectionRange(); + const int startLine = multiLineBlockMode ? qMax(0, selectionRange.start().line()) : view->cursorPosition().line(); + const int endLine = multiLineBlockMode ? qMin(selectionRange.end().line(), lastLine()) : startLine; + const int virtualColumn = toVirtualColumn(multiLineBlockMode ? selectionRange.end() : view->cursorPosition()); - removeText(r); + for (int line = endLine; line >= startLine; --line) { + Kate::TextLine textLine = m_buffer->plainLine(line); + Q_ASSERT(textLine); + const int column = fromVirtualColumn(line, virtualColumn); + KTextEditor::Range r = KTextEditor::Range(KTextEditor::Cursor(line, column), qMin(chars.length(), + textLine->length() - column)); + + // replace mode needs to know what was removed so it can be restored with backspace + if (oldCur.column() < lineLength(line)) { + QChar removed = characterAt(KTextEditor::Cursor(line, column)); + view->currentInputMode()->overwrittenChar(removed); } - } - if (multiLineBlockMode) { - KTextEditor::Range selectionRange = view->selectionRange(); - const int startLine = qMax(0, selectionRange.start().line()); - const int endLine = qMin(selectionRange.end().line(), lastLine()); - const int column = toVirtualColumn(selectionRange.end()); - for (int line = endLine; line >= startLine; --line) { - editInsertText(line, fromVirtualColumn(line, column), chars); - } - int newSelectionColumn = toVirtualColumn(view->cursorPosition()); - selectionRange.setRange(KTextEditor::Cursor(selectionRange.start().line(), fromVirtualColumn(selectionRange.start().line(), newSelectionColumn)) - , KTextEditor::Cursor(selectionRange.end().line(), fromVirtualColumn(selectionRange.end().line(), newSelectionColumn))); - view->setSelection(selectionRange); - } else { - chars = eventuallyReplaceTabs(view->cursorPosition(), chars); - insertText(view->cursorPosition(), chars); + removeText(r); } + } - /** - * auto bracket handling for newly inserted text - * we inserted a bracket? - * => add the matching closing one to the view + input chars - * try to preserve the cursor position - */ - bool skipAutobrace = closingBracket == QLatin1Char('\''); - if ( highlight() && skipAutobrace ) { - // skip adding ' in spellchecked areas, because those are text - skipAutobrace = highlight()->spellCheckingRequiredForLocation(this, view->cursorPosition() - Cursor{0, 1}); - } - if (!closingBracket.isNull() && !skipAutobrace ) { - // add bracket to the view - const auto cursorPos(view->cursorPosition()); - const auto nextChar = view->document()->text({cursorPos, cursorPos + Cursor{0, 1}}).trimmed(); - if ( nextChar.isEmpty() || ! nextChar.at(0).isLetterOrNumber() ) { - insertText(view->cursorPosition(), QString(closingBracket)); - const auto insertedAt(view->cursorPosition()); - view->setCursorPosition(cursorPos); - m_currentAutobraceRange.reset(newMovingRange({cursorPos - Cursor{0, 1}, insertedAt}, - KTextEditor::MovingRange::DoNotExpand)); - connect(view, &View::cursorPositionChanged, - this, &DocumentPrivate::checkCursorForAutobrace, Qt::UniqueConnection); - - // add bracket to chars inserted! needed for correct signals + indent - chars.append(closingBracket); - } - m_currentAutobraceClosingChar = closingBracket; + if (multiLineBlockMode) { + KTextEditor::Range selectionRange = view->selectionRange(); + const int startLine = qMax(0, selectionRange.start().line()); + const int endLine = qMin(selectionRange.end().line(), lastLine()); + const int column = toVirtualColumn(selectionRange.end()); + for (int line = endLine; line >= startLine; --line) { + editInsertText(line, fromVirtualColumn(line, column), chars); } + int newSelectionColumn = toVirtualColumn(view->cursorPosition()); + selectionRange.setRange(KTextEditor::Cursor(selectionRange.start().line(), fromVirtualColumn(selectionRange.start().line(), newSelectionColumn)) + , KTextEditor::Cursor(selectionRange.end().line(), fromVirtualColumn(selectionRange.end().line(), newSelectionColumn))); + view->setSelection(selectionRange); + } else { + chars = eventuallyReplaceTabs(view->cursorPosition(), chars); + insertText(view->cursorPosition(), chars); + } - // end edit session here, to have updated HL in userTypedChar! - editEnd(); + /** + * auto bracket handling for newly inserted text + * we inserted a bracket? + * => add the matching closing one to the view + input chars + * try to preserve the cursor position + */ + bool skipAutobrace = closingBracket == QLatin1Char('\''); + if ( highlight() && skipAutobrace ) { + // skip adding ' in spellchecked areas, because those are text + skipAutobrace = highlight()->spellCheckingRequiredForLocation(this, view->cursorPosition() - Cursor{0, 1}); + } + if (!closingBracket.isNull() && !skipAutobrace ) { + // add bracket to the view + const auto cursorPos(view->cursorPosition()); + const auto nextChar = view->document()->text({cursorPos, cursorPos + Cursor{0, 1}}).trimmed(); + if ( nextChar.isEmpty() || ! nextChar.at(0).isLetterOrNumber() ) { + insertText(view->cursorPosition(), QString(closingBracket)); + const auto insertedAt(view->cursorPosition()); + view->setCursorPosition(cursorPos); + m_currentAutobraceRange.reset(newMovingRange({cursorPos - Cursor{0, 1}, insertedAt}, + KTextEditor::MovingRange::DoNotExpand)); + connect(view, &View::cursorPositionChanged, + this, &DocumentPrivate::checkCursorForAutobrace, Qt::UniqueConnection); + + // add bracket to chars inserted! needed for correct signals + indent + chars.append(closingBracket); + } + m_currentAutobraceClosingChar = closingBracket; + } - // trigger indentation - KTextEditor::Cursor b(view->cursorPosition()); - m_indenter->userTypedChar(view, b, chars.isEmpty() ? QChar() : chars.at(chars.length() - 1)); + // end edit session here, to have updated HL in userTypedChar! + editEnd(); - /** - * inform the view about the original inserted chars - */ - view->slotTextInserted(view, oldCur, chars); - } + // trigger indentation + KTextEditor::Cursor b(view->cursorPosition()); + m_indenter->userTypedChar(view, b, chars.isEmpty() ? QChar() : chars.at(chars.length() - 1)); /** - * be done + * inform the view about the original inserted chars */ + view->slotTextInserted(view, oldCur, chars); + return true; }