Exemple #1
0
bool TabSettings::guessSpacesForTabs(const QTextBlock &_block) const
{
    if (m_tabPolicy == MixedTabPolicy && _block.isValid()) {
        const QTextDocument *doc = _block.document();
        QVector<QTextBlock> currentBlocks(2, _block); // [0] looks back; [1] looks forward
        int maxLookAround = 100;
        while (maxLookAround-- > 0) {
            if (currentBlocks.at(0).isValid())
                currentBlocks[0] = currentBlocks.at(0).previous();
            if (currentBlocks.at(1).isValid())
                currentBlocks[1] = currentBlocks.at(1).next();
            bool done = true;
            foreach (const QTextBlock &block, currentBlocks) {
                if (block.isValid())
                    done = false;
                if (!block.isValid() || block.length() == 0)
                    continue;
                const QChar firstChar = doc->characterAt(block.position());
                if (firstChar == QLatin1Char(' ')) {
                    return true;
                } else if (firstChar == QLatin1Char('\t')) {
                    return false;
                }
            }
            if (done)
                break;
        }
    }
    return m_tabPolicy != TabsOnlyTabPolicy;
}
ChangeListLevelCommand::ChangeListLevelCommand(const QTextCursor &cursor, ChangeListLevelCommand::CommandType type,
                                               int coef, KUndo2Command *parent)
    : KoTextCommandBase(parent),
      m_type(type),
      m_coefficient(coef),
      m_first(true)
{
    setText(kundo2_i18n("Change List Level"));

    int selectionStart = qMin(cursor.anchor(), cursor.position());
    int selectionEnd = qMax(cursor.anchor(), cursor.position());

    QTextBlock block = cursor.block().document()->findBlock(selectionStart);

    bool oneOf = (selectionStart == selectionEnd); //ensures the block containing the cursor is selected in that case

    while (block.isValid() && ((block.position() < selectionEnd) || oneOf)) {
        m_blocks.append(block);
        if (block.textList()) {
            m_lists.insert(m_blocks.size() - 1, KoTextDocument(block.document()).list(block.textList()));
            Q_ASSERT(m_lists.value(m_blocks.size() - 1));
            m_levels.insert(m_blocks.size() - 1, effectiveLevel(m_lists.value(m_blocks.size() - 1)->level(block)));
        }
        oneOf = false;
        block = block.next();
    }
}
void CodeFormatter::updateStateUntil(const QTextBlock &endBlock)
{
    QStack<State> previousState = initialState();
    QTextBlock it = endBlock.document()->firstBlock();

    // find the first block that needs recalculation
    for (; it.isValid() && it != endBlock; it = it.next()) {
        BlockData blockData;
        if (!loadBlockData(it, &blockData))
            break;
        if (blockData.m_blockRevision != it.revision())
            break;
        if (previousState != blockData.m_beginState)
            break;
        if (loadLexerState(it) == -1)
            break;

        previousState = blockData.m_endState;
    }

    if (it == endBlock)
        return;

    // update everthing until endBlock
    for (; it.isValid() && it != endBlock; it = it.next()) {
        recalculateStateAfter(it);
    }

    // invalidate everything below by marking the state in endBlock as invalid
    if (it.isValid()) {
        BlockData invalidBlockData;
        saveBlockData(&it, invalidBlockData);
    }
}
Exemple #4
0
QString ToCGenerator::fetchBookmarkRef(const QTextBlock &block, KoTextRangeManager *textRangeManager)
{
    QHash<int, KoTextRange *> ranges = textRangeManager->textRangesChangingWithin(block.document(), block.position(), block.position() + block.length(), block.position(), block.position() + block.length());

    foreach (KoTextRange *range, ranges) {
        KoBookmark *bookmark = dynamic_cast<KoBookmark *>(range);
        if (bookmark) {
            return bookmark->name();
        }
    }
int AutoCompleter::paragraphSeparatorAboutToBeInserted(QTextCursor &cursor)
{
    QTextBlock block = cursor.block();
    const QString text = block.text().trimmed();
    if (text == "end"
            || text == "else"
            || text.startsWith("elsif")
            || text.startsWith("rescue")
            || text == "ensure") {
        Indenter indenter(const_cast<QTextDocument*>(block.document()));
        indenter.indentBlock(block, QChar(), tabSettings());
    }

    return 0;
    // This implementation is buggy
#if 0
    const QString textFromCursor = text.mid(cursor.positionInBlock()).trimmed();
    if (!textFromCursor.isEmpty())
        return 0;

    if (Language::symbolDefinition.indexIn(text) == -1
            && Language::startOfBlock.indexIn(text) == -1) {
        return 0;
    }

    int spaces = 0;
    for (const QChar c : text) {
        if (!c.isSpace())
            break;
        spaces++;
    }
    QString indent = text.left(spaces);

    QString line;
    QTextBlock nextBlock = block.next();
    while (nextBlock.isValid()) {
        line = nextBlock.text();
        if (Language::endKeyword.indexIn(line) != -1 && line.startsWith(indent))
            return 0;
        if (!line.trimmed().isEmpty())
            break;
        nextBlock = nextBlock.next();
    }

    int pos = cursor.position();
    cursor.insertBlock();
    cursor.insertText("end");
    cursor.setPosition(pos);

    return 1;
#endif
}
// Add extra text in case of the empty line or the line starting with ')'.
// Track such extra pieces of text in isInsideModifiedLine().
int forceIndentWithExtraText(QByteArray &buffer, const QTextBlock &block, bool secondTry)
{
    const QString blockText = block.text();
    int firstNonWhitespace = Utils::indexOf(blockText,
                                            [](const QChar &ch) { return !ch.isSpace(); });
    int utf8Offset = Utils::Text::utf8NthLineOffset(block.document(),
                                                    buffer,
                                                    block.blockNumber() + 1);
    if (firstNonWhitespace > 0)
        utf8Offset += firstNonWhitespace;
    else
        utf8Offset += blockText.length();

    const bool closingParenBlock = firstNonWhitespace >= 0
                                   && blockText.at(firstNonWhitespace) == ')';

    int extraLength = 0;
    if (firstNonWhitespace < 0 || closingParenBlock) {
        //This extra text works for the most cases.
        QByteArray dummyText("a;a;");

        // Search for previous character
        QTextBlock prevBlock = block.previous();
        bool prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty();
        while (prevBlockIsEmpty) {
            prevBlock = prevBlock.previous();
            prevBlockIsEmpty = prevBlock.position() > 0 && prevBlock.text().trimmed().isEmpty();
        }
        if (closingParenBlock || prevBlock.text().endsWith(','))
            dummyText = "&& a";

        buffer.insert(utf8Offset, dummyText);
        extraLength += dummyText.length();
    }

    if (secondTry) {
        int nextLinePos = buffer.indexOf('\n', utf8Offset);
        if (nextLinePos < 0)
            nextLinePos = buffer.size() - 1;

        if (nextLinePos > 0) {
            // If first try was not successful try to put ')' in the end of the line to close possibly
            // unclosed parentheses.
            // TODO: Does it help to add different endings depending on the context?
            buffer.insert(nextLinePos, ')');
            extraLength += 1;
        }
    }

    return extraLength;
}
int formattingRangeStart(const QTextBlock &currentBlock,
                         const QByteArray &buffer,
                         int documentRevision)
{
    QTextBlock prevBlock = currentBlock.previous();
    while ((prevBlock.position() > 0 || prevBlock.length() > 0)
           && prevBlock.revision() != documentRevision) {
        // Find the first block with not matching revision.
        prevBlock = prevBlock.previous();
    }
    if (prevBlock.revision() == documentRevision)
        prevBlock = prevBlock.next();

    return Utils::Text::utf8NthLineOffset(prevBlock.document(), buffer, prevBlock.blockNumber() + 1);
}
int indentationForBlock(const TextEditor::Replacements &toReplace,
                        const QByteArray &buffer,
                        const QTextBlock &currentBlock)
{
    const int utf8Offset = Utils::Text::utf8NthLineOffset(currentBlock.document(),
                                                          buffer,
                                                          currentBlock.blockNumber() + 1);
    auto replacementIt = std::find_if(toReplace.begin(),
                                      toReplace.end(),
                                      [utf8Offset](const TextEditor::Replacement &replacement) {
                                          return replacement.offset == utf8Offset - 1;
                                      });
    if (replacementIt == toReplace.end())
        return -1;

    int afterLineBreak = replacementIt->text.lastIndexOf('\n');
    afterLineBreak = (afterLineBreak < 0) ? 0 : afterLineBreak + 1;
    return static_cast<int>(replacementIt->text.size() - afterLineBreak);
}
Exemple #9
0
static int findClosingConstruct(const QTextBlock &block) {
  if (!block.isValid()) return -1;

  TextBlockData *blockData = reinterpret_cast<TextBlockData*>(block.userData());
  if (!blockData) return -1;
  if (blockData->bracketPositions.isEmpty()) return -1;

  const QTextDocument *doc = block.document();
  int offset = block.position();

  foreach (int pos, blockData->bracketPositions) {
    int absPos = offset + pos;
    if (doc->characterAt(absPos) == '{') {
      int matchPos = findClosingMatch(doc, absPos);
      if (matchPos >= 0) return matchPos;
    }
  }

  return -1;
}
Exemple #10
0
QHash<QTextList *, QString> KoTextWriter::saveListStyles(QTextBlock block, int to)
{
    QHash<KoList *, QString> generatedLists;
    QHash<QTextList *, QString> listStyles;
    KoTextDocument document(block.document());

    for (;block.isValid() && ((to == -1) || (block.position() < to)); block = block.next()) {
        QTextList *textList = block.textList();
        if (!textList)
            continue;
        if (KoList *list = document.list(block)) {
            if (generatedLists.contains(list)) {
                if (!listStyles.contains(textList))
                    listStyles.insert(textList, generatedLists.value(list));
                continue;
            }
            KoListStyle *listStyle = list->style();
            bool automatic = listStyle->styleId() == 0;
            KoGenStyle style(automatic ? KoGenStyle::StyleListAuto : KoGenStyle::StyleList);
            listStyle->saveOdf(style);
            QString generatedName = d->context.mainStyles().lookup(style, listStyle->name(), KoGenStyles::AllowDuplicates);
            listStyles[textList] = generatedName;
            generatedLists.insert(list, generatedName);
        } else {
            if (listStyles.contains(textList))
                continue;
            KoListLevelProperties llp = KoListLevelProperties::fromTextList(textList);
            KoGenStyle style(KoGenStyle::StyleListAuto);
            KoListStyle listStyle;
            listStyle.setLevelProperties(llp);
            listStyle.saveOdf(style);
            QString generatedName = d->context.mainStyles().lookup(style, listStyle.name());
            listStyles[textList] = generatedName;
        }
    }
    return listStyles;
}
Exemple #11
0
void GoCodeFormatter::updateStateUntil(const QTextBlock &endBlock)
{
    QStack<CodeState> previousState = initialState();
    QTextBlock it = endBlock.document()->firstBlock();

    // find the first block that needs recalculation
    while (it.isValid() && it != endBlock) {
        BlockData blockData;
        if (!loadBlockData(it, &blockData))
            break;
        if (blockData.revision != it.revision())
            break;
        if (previousState.isEmpty() || blockData.beginState.isEmpty()
                || previousState != blockData.beginState)
            break;
        if (TextEditor::TextDocumentLayout::lexerState(endBlock) == -1)
            break;

        previousState = blockData.endState;
        it = it.next();
    }

    if (it == endBlock) // No need to recalculate
        return;

    // update everthing until endBlock
    while (it.isValid() && it != endBlock) {
        recalculateStateAfter(it);
        it = it.next();
    }

    // invalidate everything below by marking the state in endBlock as invalid
    if (it.isValid()) {
        BlockData invalidBlockData;
        saveBlockData(&it, invalidBlockData);
    }
}