QTextCursor ScCodeEditor::selectionForPosition( int position ) { QTextBlock block( textDocument()->findBlock(position) ); if (!block.isValid()) return QTextCursor(); int positionInBlock = position - block.position(); TokenIterator it = TokenIterator( block, positionInBlock ); if (it.type() == Token::Unknown) { // Token is invalid, or Token::Unknown (i.e. punctuations). // Prefer token at previous position. TokenIterator alternativeIt = TokenIterator( block, positionInBlock - 1 ); if (alternativeIt.isValid()) it = alternativeIt; } if (it.isValid()) { switch (it->type) { case Token::OpeningBracket: case Token::ClosingBracket: { BracketPair match; matchBracket(it, match); if (match.first.isValid() && match.second.isValid()) { int start = match.first.position(); int end = match.second.position() + 1; QTextCursor selection(textDocument()); if (it == match.second) { selection.setPosition(start); selection.setPosition(end, QTextCursor::KeepAnchor); } else { selection.setPosition(end); selection.setPosition(start, QTextCursor::KeepAnchor); } return selection; } break; } default: QTextCursor selection( textDocument() ); selection.setPosition( it.position() ); selection.setPosition( selection.position() + it->length, QTextCursor::KeepAnchor ); return selection; } } return QTextCursor(); }
void ScCodeEditor::matchBracket( const TokenIterator & bracket, BracketPair & match ) { Q_ASSERT(bracket.isValid()); switch(bracket->type) { case Token::OpeningBracket: match.first = bracket; match.second = nextClosingBracket(bracket.next()); break; case Token::ClosingBracket: match.second = bracket; match.first = previousOpeningBracket(bracket.previous()); break; default: match.first = TokenIterator(); match.second = TokenIterator(); } }
void ScCodeEditor::matchBrackets() { mBracketSelections.clear(); QTextCursor cursor(textCursor()); QTextBlock block( cursor.block() ); int posInBlock = cursor.positionInBlock(); TokenIterator it(block); while (it.isValid() && it.block() == block) { const Token & token = *it; if (token.positionInBlock > posInBlock) { it = TokenIterator(); break; } else if ( (token.positionInBlock == posInBlock && token.type == Token::OpeningBracket) || (token.positionInBlock == posInBlock - 1 && token.type == Token::ClosingBracket) ) break; ++it; } BracketPair match; if( it.isValid() && it.block() == block) matchBracket( it, match ); if( match.first.isValid() && match.second.isValid() ) { const Token & tok1 = *match.first; const Token & tok2 = *match.second; if ( (tok1.character == '(' && tok2.character == ')') || (tok1.character == '[' && tok2.character == ']') || (tok1.character == '{' && tok2.character == '}') ){ QTextEdit::ExtraSelection selection; selection.format = mBracketHighlight; cursor.setPosition(match.first.position()); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); selection.cursor = cursor; mBracketSelections.append(selection); cursor.setPosition(match.second.position()); cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); selection.cursor = cursor; mBracketSelections.append(selection); if (mHighlightBracketContents) { QTextCharFormat format; format.setBackground( mBracketHighlight.background() ); selection.format = format; cursor.setPosition(match.first.position()+1); cursor.setPosition(match.second.position(), QTextCursor::KeepAnchor); selection.cursor = cursor; mBracketSelections.append(selection); } } else { QTextEdit::ExtraSelection selection; selection.format = mBracketMismatchFormat; cursor.setPosition(match.first.position()); cursor.setPosition(match.second.position()+1, QTextCursor::KeepAnchor); selection.cursor = cursor; mBracketSelections.append(selection); } } updateExtraSelections(); }