// Reset the header state of a here-doc to 7 // and the state of its body to 6. void Highlighter::resetHereDocStates (QTextBlock block) { if (block.userState() == hereDocTempState) { block.setUserState (hereDocHeaderState); block = block.next(); while (block.isValid() && block.userState() != 0) { block.setUserState (hereDocBodyState); block = block.next(); } } }
void CppHighlighter::highlightBlock(QTextBlock& b) { BlockData *blockData = BlockData::data(b); if ( !blockData ) { blockData = new BlockData; blockData->setToBlock(b); } b.setUserState( process(b.text(), blockData) ); //if ( e-> ) if (blockData->parenthesisMatchStart != -1) { QTextCharFormat fmt = format(blockData->parenthesisMatchStart); blockData->parenthesisMatchingFormat.setProperty( ParenthesisMatcherPropertyId, qVariantFromValue(fmt) ); fmt.merge(blockData->parenthesisMatchingFormat); setFormat(blockData->parenthesisMatchStart, 1, fmt); } if (blockData->parenthesisMatchEnd != -1) { QTextCharFormat fmt = format(blockData->parenthesisMatchEnd); blockData->parenthesisMatchingFormat.setProperty( ParenthesisMatcherPropertyId, qVariantFromValue(fmt) ); fmt.merge(blockData->parenthesisMatchingFormat); setFormat(blockData->parenthesisMatchEnd, 1, fmt); } }
void BaseTextDocumentLayout::setBraceDepth(QTextBlock &block, int depth) { int state = block.userState(); if (state == -1) state = 0; state = state & 0xff; block.setUserState((depth << 8) | state); }
void AssistInterface::recreateTextDocument() { m_textDocument = new QTextDocument(m_text); m_text.clear(); QTC_CHECK(m_textDocument->blockCount() == m_userStates.count()); QTextBlock block = m_textDocument->firstBlock(); for (int i = 0; i < m_userStates.count() && block.isValid(); ++i, block = block.next()) block.setUserState(m_userStates[i]); }
void TextEditor::pcChanged(ParseNode *pc, bool justRolledBack) { ParseNode *old = m_pc; // cerr << "\tpcChanged id:" << QThread::currentThreadId() << "\n"; if (old == pc) return; m_pc = pc; // if (m_program->getStatus() != PAUSED) // return; if (old != NULL) { QTextBlock *b = old->getTextBlock(); int state = b->userState(); if (state > 0) b->setUserState(state & ~B_CURRENT_PC); } if (m_pc != NULL) { QTextBlock *b = m_pc->getTextBlock(); // cerr << "b: " << b->text().toStdString() << endl; int state = b->userState(); if (state < 0) b->setUserState(B_CURRENT_PC); else b->setUserState(state | B_CURRENT_PC); if (!justRolledBack && b != NULL) { QTextCursor c = textCursor(); c.setPosition(b->position()); setTextCursor(c); ensureCursorVisible(); } } m_parent->updateLineNumbers(0); // the 2 can be changed according to preferences later // just be sure to also change the fading factors in paintEvent. m_program->getLastXInstructions(Options::noPreviousXInstructions(), m_lastInstructions); viewport()->update(); }
void CodeEditor::foldUnfold(QTextBlock& block) { int state = block.userState(); if (state & Error || state & End || !(state & Begin) || // (state & End) для однострочного блока () document()->lastBlock() == block) return; bool unfolding = state & Folded; if (unfolding) block.setUserState(block.userState() & ~Folded); else block.setUserState(block.userState() | Folded); int previousBlockState = block.previous().userState(); int endBraceDepth = previousBlockState & Error ? 0 : previousBlockState >> StateShift; int braceDepth; int skipDepth = 0; while ((block = block.next()).isValid()) { int state = block.userState(); braceDepth = state >> StateShift; if (unfolding) { if (state & Begin && !skipDepth && state & Folded) { skipDepth = block.previous().userState() >> StateShift; } else if (skipDepth) { if (braceDepth == skipDepth) skipDepth = 0; continue; } }
QString LiteEditorWidget::cursorToHtml(QTextCursor cursor) const { QTextDocument *tempDocument = new QTextDocument; QTextCursor tempCursor(tempDocument); tempCursor.insertFragment(cursor.selection()); // Apply the additional formats set by the syntax highlighter QTextBlock start = document()->findBlock(cursor.selectionStart()); QTextBlock end = document()->findBlock(cursor.selectionEnd()); end = end.next(); const int selectionStart = cursor.selectionStart(); const int endOfDocument = tempDocument->characterCount() - 1; for (QTextBlock current = start; current.isValid() && current != end; current = current.next()) { const QTextLayout *layout = current.layout(); foreach (const QTextLayout::FormatRange &range, layout->additionalFormats()) { const int start = current.position() + range.start - selectionStart; const int end = start + range.length; if (end <= 0 || start >= endOfDocument) continue; tempCursor.setPosition(qMax(start, 0)); tempCursor.setPosition(qMin(end, endOfDocument), QTextCursor::KeepAnchor); tempCursor.setCharFormat(range.format); } } // Reset the user states since they are not interesting for (QTextBlock block = tempDocument->begin(); block.isValid(); block = block.next()) block.setUserState(-1); // Make sure the text appears pre-formatted tempCursor.setPosition(0); tempCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); QTextBlockFormat blockFormat = tempCursor.blockFormat(); blockFormat.setNonBreakableLines(true); tempCursor.setBlockFormat(blockFormat); QString html = tempCursor.selection().toHtml();//("utf-8"); html.replace("\t","    "); delete tempDocument; return html; }
void CodeEditor::contentsChange(int pos, int, int) { QTextBlock block = textCursor().block(); // сдвиг блока клавишей Return // состояние предыдущего блока может быть не верным if (block.userState() == Empty) block.setUserState(block.previous().userState() | Rehighligh); block = document()->findBlock(pos); int startBlockNum = block.blockNumber(); bool forceUnfold = false; while (block.isValid()) { int previousState = block.userState(); int state = setBlockState(block); if (!(previousState & Error) && !(state & Error) && previousState & Comment && state & Comment) { QTextBlock next = block.next(); int nextBlockState = next.userState(); setBlockState(next); next.setUserState(nextBlockState); // в начальное состояние // правильное состояние комментария известно // только после обработки последующей строки state = block.userState(); } if (state != previousState) { if (!forceUnfold) { // разворачиваем предыдущие блоки QTextBlock previous = block.previous(); while (previous.isValid()) { int state = previous.userState(); if (!(state & Error) && state & Folded) previous.setUserState(state & ~Folded); if (state & Error || !(state & Nested) || previous.isVisible()) break; previous.setVisible(true); previous = previous.previous(); } } forceUnfold = true; } else if (block.blockNumber() > startBlockNum && // не начальный блок state & Begin && !(state & Nested)) { // (state & Begin ...) пропускаем End главного блока break; // без state & Error, иначе срабатывает между блоками } // при первом обновлении if (forceUnfold) { // разворачиваем последующие блоки if (!(state & Error) && state & Folded) state &= ~Folded; block.setVisible(true); } block.setUserState(state | Rehighligh); block = block.next(); } }
int CodeEditor::setBlockState(QTextBlock& block) { int previousBlockState = block.previous().userState(); if (previousBlockState & Error) previousBlockState = 0; bool inString = previousBlockState & String; int previousBraceDepth = previousBlockState >> StateShift; int braceDepth = previousBraceDepth; QString txt = block.text(); int state = 0; int i = 0; while (txt[i].isSpace()) ++i; if (txt[i] == ';') { if (!previousBraceDepth || previousBlockState & Comment) { state |= Comment; // только за предалами блока кода if (previousBlockState & Comment) { if (braceDepth) { braceDepth--; } else { previousBraceDepth = 1; previousBlockState = (previousBlockState & End ? Nested : Begin) | (previousBlockState & Folded) | (previousBlockState & Rehighligh); previousBlockState |= (previousBraceDepth << StateShift) | Comment; block.previous().setUserState(previousBlockState); } state |= End; } } } else { // коррекция блока после удаления строки комментария if (previousBlockState & Comment && previousBlockState & (Nested | Begin)) { previousBraceDepth = 0; braceDepth = 0; previousBlockState = previousBlockState & Nested ? End : 0; previousBlockState |= (previousBraceDepth << StateShift) | Comment; block.previous().setUserState(previousBlockState); } if (txt[i].isNull() && !previousBraceDepth) { // пустая строка //qDebug() << "*** Error #1 'empty string'"; state = Empty; } else if (txt[i] != '(' && !previousBraceDepth) { // начальный символ вне блока не '(' или ';' //qDebug() << "*** Error #2 'bad begin'"; braceDepth = i; // позиция начала ошибки state |= Error; } else { while (i < txt.length()) { if (txt[i] == '"' && !(i && txt[i - 1] == '\\')) { inString = !inString; } else if (!inString) { if (txt[i] == ';') // комментарий в блоке кода break; if (txt[i] == '(') braceDepth++; else if (txt[i] == ')') braceDepth--; if (braceDepth == -1) { //qDebug() << "*** Error #3 ') mismatch'"; braceDepth = i; state |= Error; break; } } i++; } // while } } if (!(state & (Error | Comment))) { if (inString) state |= String; if (braceDepth > previousBraceDepth || !previousBraceDepth) state |= Begin; if (braceDepth < previousBraceDepth || !braceDepth) state |= End; if (previousBraceDepth && braceDepth) state |= Nested; } state |= (braceDepth << StateShift); int previousState = block.userState(); if (previousState != Empty) state |= (previousState & Folded) | (previousState & Rehighligh); // qDebug("Block[%d]\n" // "\tDepth %d/%d State %d/%d New %d", // block.blockNumber(), // braceDepth, previousBraceDepth, // state, block.userState(), // (bool)(previousState != state)); // if (state & Error) // qDebug("\tError position %d", braceDepth); // else // qDebug("\tEnd:%d Begin:%d String:%d Comment:%d Nested:%d Folded:%d", // (bool)(state & End), (bool)(state & Begin), // (bool)(state & String), (bool)(state & Comment), // (bool)(state & Nested), (bool)(state & Folded)); // if (previousState & Error) // qDebug("\t[P] Error position %d", braceDepth); // else // qDebug("\t[P] End:%d Begin:%d String:%d Comment:%d Nested:%d Folded:%d", // (bool)(previousState & End), (bool)(previousState & Begin), // (bool)(previousState & String), (bool)(previousState & Comment), // (bool)(previousState & Nested), (bool)(previousState & Folded)); block.setUserState(state); return state; }
void CodeEditor::extraAreaPaintEvent() { QTextBlock block = firstVisibleBlock(); QPainter painter(extraArea); QPen pen = painter.pen(); QFont font = painter.font(); bool bold = font.bold(); int y = 0; int cx = lineNumWidth + foldBoxIndent + foldBoxWidth / 2; // центр маркера блока по x do { if (!block.isVisible()) continue; QRectF rect = blockBoundingGeometry(block); y = rect.translated(contentOffset()).y(); if (block == textCursor().block()) { painter.setPen(Qt::yellow); font.setBold(!bold); } else { font.setBold(bold); } painter.setFont(font); painter.drawText(0, y, lineNumWidth, fontMetrics().height(), Qt::AlignRight, QString::number(block.blockNumber() + 1)); // номер строки painter.setPen(pen); int state = block.userState(); int cy = y + fontMetrics().height() / 2; // центр маркера по Y if (!(state & Error) && !(state & Begin && state & End && !(state & Nested))) { if (state & Begin) { if (state & Comment) painter.drawEllipse(FOLDBOXRECT(cy)); else painter.drawRoundedRect(FOLDBOXRECT(cy), 7, 3); if (!(!(state & Nested) && state & Folded)) painter.drawLine(cx, cy + foldBoxWidth / 2, cx, y + rect.height()); // края маркера вниз if (state & Nested) painter.drawLine(cx, y, cx, cy - foldBoxWidth / 2); // края маркера вверх painter.drawLine(cx - foldBoxLength, cy, cx + foldBoxLength, cy); // горизонтальная линия внутри маркера if (state & Folded) painter.drawLine(cx, cy - foldBoxLength, cx, cy + foldBoxLength); // вертикальная линия внутри маркера } else if (state & End) { painter.drawLine(cx, cy, cx + foldBoxLength, cy); // от центра вправо if (state & Nested) painter.drawLine(cx, y, cx, y + rect.height()); // вертикальная линия else painter.drawLine(cx, y, cx, cy); // от центра вверх } else if (state & Nested) { painter.drawLine(cx, y, cx, y + rect.height()); // вертикальная линия } } // в paintEvent не работает if (state != Empty && state & Rehighligh) { highlighter->rehighlightBlock(block); block.setUserState(state & ~Rehighligh); } } while ((block = block.next()).isValid() && y < viewport()->height()); }
void DevHighlighter::highlightBlock(QTextBlock& b) { b.setUserState( process(b.text(), BlockData::data(b)) ); }