static bool isInStringHelper(const QTextCursor &cursor, Token *retToken = 0) { LanguageFeatures features; features.qtEnabled = false; features.qtKeywordsEnabled = false; features.qtMocRunEnabled = false; features.cxx11Enabled = true; features.c99Enabled = true; SimpleLexer tokenize; tokenize.setLanguageFeatures(features); const int prevState = BackwardsScanner::previousBlockState(cursor.block()) & 0xFF; const Tokens tokens = tokenize(cursor.block().text(), prevState); const unsigned pos = cursor.selectionEnd() - cursor.block().position(); if (tokens.isEmpty() || pos <= tokens.first().utf16charsBegin()) return false; if (pos >= tokens.last().utf16charsEnd()) { const Token tk = tokens.last(); return tk.isStringLiteral() && prevState > 0; } Token tk = tokenAtPosition(tokens, pos); if (retToken) *retToken = tk; return tk.isStringLiteral() && pos > tk.utf16charsBegin(); }
void CellEditor::Private::updateActiveSubRegion(const Tokens &tokens) { // Index of the token, at which the text cursor is positioned. // For sub-regions it is the start range. currentToken = 0; if (tokens.isEmpty()) { selection->setActiveSubRegion(0, 0); // also set the active element return; } const int cursorPosition = textEdit->textCursor().position() - 1; // without '=' kDebug() << "cursorPosition:" << cursorPosition << "textLength:" << textEdit->toPlainText().length() - 1; uint rangeCounter = 0; // counts the ranges in the sub-region uint currentRange = 0; // range index denoting the current range int regionStart = 0; // range index denoting the sub-region start uint regionEnd = 0; // range index denoting the sub-region end enum { Anywhere, InRegion, BeyondCursor } state = Anywhere; Token token; Token::Type type; // Search the current range the text cursor is positioned to. // Determine the subregion start and end, in which the range is located. for (int i = 0; i < tokens.count(); ++i) { token = tokens[i]; type = token.type(); // If not in a subregion, we may already quit the loop here. if (state == Anywhere) { // Already beyond the cursor position? if (token.pos() > cursorPosition) { state = BeyondCursor; break; // for loop } } else if (state == InRegion) { // Loop to the end of the subregion. if (type == Token::Cell || type == Token::Range) { regionEnd = rangeCounter++; continue; // keep going until the referenced region ends } if (type == Token::Operator) { if (tokens[i].asOperator() == Token::Semicolon) { continue; // keep going until the referenced region ends } } state = Anywhere; continue; } // Can the token be replaced by a reference? switch (type) { case Token::Cell: case Token::Range: if (state == Anywhere) { currentToken = i; regionStart = rangeCounter; state = InRegion; } regionEnd = rangeCounter; // length = 1 currentRange = ++rangeCounter; // point behind the last continue; case Token::Unknown: case Token::Boolean: case Token::Integer: case Token::Float: case Token::String: case Token::Error: // Set the active sub-region start to the next range but // with a length of 0, which results in inserting a new range // to the selection on calling Selection::initialize() or // Selection::update(). currentToken = i; regionStart = rangeCounter; // position of the next range regionEnd = rangeCounter - 1; // length = 0 currentRange = rangeCounter; continue; case Token::Operator: case Token::Identifier: continue; } } // Cursor not reached? I.e. the cursor is placed at the last token's end. if (state == Anywhere) { token = tokens.last(); type = token.type(); // Check the last token. // It was processed, but maybe a reference can be placed behind it. // Check, if the token can be replaced by a reference. switch (type) { case Token::Operator: // Possible to place a reference behind the operator? switch (token.asOperator()) { case Token::Plus: case Token::Minus: case Token::Asterisk: case Token::Slash: case Token::Caret: case Token::LeftPar: case Token::Semicolon: case Token::Equal: case Token::NotEqual: case Token::Less: case Token::Greater: case Token::LessEqual: case Token::GreaterEqual: case Token::Intersect: case Token::Union: // Append new references by pointing behind the last. currentToken = tokens.count(); regionStart = rangeCounter; regionEnd = rangeCounter - 1; // length = 0 currentRange = rangeCounter; break; case Token::InvalidOp: case Token::RightPar: case Token::Comma: case Token::Ampersand: case Token::Percent: case Token::CurlyBra: case Token::CurlyKet: case Token::Pipe: // reference cannot be placed behind break; } break; case Token::Unknown: case Token::Boolean: case Token::Integer: case Token::Float: case Token::String: case Token::Identifier: case Token::Error: // currentToken = tokens.count() - 1; // already set // Set the active sub-region start to the end of the selection // with a length of 0, which results in appending a new range // to the selection on calling Selection::initialize() or // Selection::update(). regionStart = rangeCounter; regionEnd = rangeCounter - 1; // length = 0 currentRange = rangeCounter; break; case Token::Cell: case Token::Range: // currentToken = tokens.count() - 1; // already set // Set the last range as active one. It is not a sub-region, // otherwise the state would have been InRegion. regionStart = rangeCounter - 1; regionEnd = rangeCounter - 1; // length = 1 currentRange = rangeCounter; // point behind the last break; } } const int regionLength = regionEnd - regionStart + 1; kDebug() << "currentRange:" << currentRange << "regionStart:" << regionStart << "regionEnd:" << regionEnd << "regionLength:" << regionLength; selection->setActiveSubRegion(regionStart, regionLength, currentRange); }