diff --git a/src/plugins/texteditor/textdocument.cpp b/src/plugins/texteditor/textdocument.cpp index ae574bc0ba6..4b2e09caf96 100644 --- a/src/plugins/texteditor/textdocument.cpp +++ b/src/plugins/texteditor/textdocument.cpp @@ -169,35 +169,82 @@ QTextCursor TextDocumentPrivate::indentOrUnindent(const QTextCursor &textCursor, cursor.removeSelectedText(); } else { // Indent or unindent at cursor position + int maxTargetColumn = -1; + + class BlockIndenter + { + public: + BlockIndenter(const QTextBlock &_block, + const int column, + const TabSettings &_tabSettings) + : block(_block) + , text(block.text()) + , tabSettings(_tabSettings) + { + indentPosition = tabSettings.positionAtColumn(text, column, nullptr, true); + spaces = tabSettings.spacesLeftFromPosition(text, indentPosition); + } + + void indent(const int targetColumn) const + { + const int startColumn = tabSettings.columnAt(text, indentPosition - spaces); + QTextCursor cursor(block); + cursor.setPosition(block.position() + indentPosition); + cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor); + cursor.removeSelectedText(); + cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, 0, block)); + } + + int targetColumn(bool doIndent) const + { + const int optimumTargetColumn + = tabSettings.indentedColumn(tabSettings.columnAt(block.text(), indentPosition), + doIndent); + const int minimumTargetColumn = tabSettings.columnAt(text, indentPosition - spaces); + return std::max(optimumTargetColumn, minimumTargetColumn); + } + + const QTextBlock &textBlock() { return block; } + + private: + QTextBlock block; + const QString text; + int indentPosition; + int spaces; + const TabSettings &tabSettings; + }; + + std::vector blocks; + for (QTextBlock block = startBlock; block != endBlock; block = block.next()) { QString text = block.text(); - int blockColumn = tabSettings.columnAt(text, text.size()); + const int blockColumn = tabSettings.columnAt(text, text.size()); if (blockColumn < column) { cursor.setPosition(block.position() + text.size()); cursor.insertText(tabSettings.indentationString(blockColumn, column, 0, block)); text = block.text(); } - int indentPosition = tabSettings.positionAtColumn(text, column, nullptr, true); - int spaces = tabSettings.spacesLeftFromPosition(text, indentPosition); - int startColumn = tabSettings.columnAt(text, indentPosition - spaces); - int targetColumn = tabSettings.indentedColumn( - tabSettings.columnAt(text, indentPosition), doIndent); - cursor.setPosition(block.position() + indentPosition); - cursor.setPosition(block.position() + indentPosition - spaces, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - cursor.insertText(tabSettings.indentationString(startColumn, targetColumn, 0, block)); + blocks.emplace_back(BlockIndenter(block, column, tabSettings)); + maxTargetColumn = std::max(maxTargetColumn, blocks.back().targetColumn(doIndent)); } + for (const BlockIndenter &blockIndenter : blocks) + blockIndenter.indent(maxTargetColumn); + // Preserve initial anchor of block selection if (blockSelection) { - end = cursor.position(); - if (offset) { - *offset = tabSettings.columnAt(cursor.block().text(), cursor.positionInBlock()) - - column; - } - cursor.setPosition(start); - cursor.setPosition(end, QTextCursor::KeepAnchor); + if (offset) + *offset = maxTargetColumn - column; + startBlock = pos < anchor ? blocks.front().textBlock() : blocks.back().textBlock(); + start = startBlock.position() + + tabSettings.positionAtColumn(startBlock.text(), maxTargetColumn); + endBlock = pos > anchor ? blocks.front().textBlock() : blocks.back().textBlock(); + end = endBlock.position() + + tabSettings.positionAtColumn(endBlock.text(), maxTargetColumn); + + cursor.setPosition(end); + cursor.setPosition(start, QTextCursor::KeepAnchor); } }