diff --git a/gui/qt/datawidget.cpp b/gui/qt/datawidget.cpp index 8c156cba9..ee9ebf6b5 100644 --- a/gui/qt/datawidget.cpp +++ b/gui/qt/datawidget.cpp @@ -6,6 +6,10 @@ DataWidget::DataWidget(QWidget *parent) : QPlainTextEdit{parent} { moveable = false; + highlighter = new AsmHighlighter(document()); + QFont font = this->font(); + font.setStyleHint(QFont::TypeWriter); + setFont(font); setContextMenuPolicy(Qt::CustomContextMenu); } @@ -15,6 +19,8 @@ void DataWidget::updateDarkMode() { selection.format.setBackground(selection.format.colorProperty(QTextFormat::UserProperty + darkMode)); } updateAllHighlights(); + delete highlighter; + highlighter = new AsmHighlighter(document()); } void DataWidget::clearAllHighlights() { @@ -25,6 +31,8 @@ void DataWidget::clearAllHighlights() { highlights.clear(); updateAllHighlights(); + delete highlighter; + highlighter = new AsmHighlighter(document()); } void DataWidget::updateAllHighlights() { @@ -118,3 +126,75 @@ void DataWidget::highlightCurrentLine() { } } } + +AsmHighlighter::AsmHighlighter(QTextDocument *parent) : QSyntaxHighlighter(parent) { + HighlightingRule rule; + bool darkMode = isRunningInDarkMode(); + + addressFormat.setForeground(QColor(darkMode ? "#888" : "#444")); + addressFormat.setFontWeight(QFont::Bold); + + watchRFormat.setForeground(QColor("#008000")); + watchRFormat.setFontWeight(QFont::Bold); + watchWFormat.setForeground(QColor("#808000")); + watchWFormat.setFontWeight(QFont::Bold); + breakPFormat.setForeground(QColor("#800000")); + breakPFormat.setFontWeight(QFont::Bold); + + mnemonicFormat.setForeground(QColor(darkMode ? "darkorange" : "darkblue")); + + symbolFormat.setFontWeight(disasm.bold_sym ? QFont::DemiBold : QFont::Normal); + rule.pattern = QRegularExpression("\\b\\w+\\b"); + rule.format = symbolFormat; + highlightingRules.append(rule); + + decimalFormat.setForeground(QColor(darkMode ? "lime" : "green")); + rule.pattern = QRegularExpression("\\b\\d+\\b"); + rule.format = decimalFormat; + highlightingRules.append(rule); + + registerFormat.setForeground(QColor(darkMode ? "magenta" : "purple")); + rule.pattern = QRegularExpression("\\b([abcdehlirmpz]|af|bc|de|hl|sp|i[xy][hl]?|mb|n[cz]|p[eo])\\b", QRegularExpression::CaseInsensitiveOption); + rule.format = registerFormat; + highlightingRules.append(rule); + + hexFormat.setForeground(QColor(darkMode ? "lime" : "green")); + rule.pattern = QRegularExpression("\\$[0-9a-fA-F]+\\b"); + rule.format = hexFormat; + highlightingRules.append(rule); + + parenFormat.setForeground(QColor(darkMode ? "lightblue" : "navy")); + rule.pattern = QRegularExpression("[()]"); + rule.format = parenFormat; + highlightingRules.append(rule); + + labelPattern = QRegularExpression(QStringLiteral("^(%1)\\s+(\\S+):") + .arg(disasm.addr ? QStringLiteral("[0-9a-fA-F]+") : QString())); + instructionPattern = QRegularExpression(QStringLiteral("^(%1) ([ R])([ W])([ X])\\s+(%2)\\s+(\\S+)") + .arg(disasm.addr ? QStringLiteral("[0-9a-fA-F]+") : QString(), + disasm.bytes ? QStringLiteral("[0-9a-fA-F]+") : QStringLiteral(" "))); +} + +void AsmHighlighter::highlightBlock(const QString &text) { + QRegularExpressionMatch match; + if ((match = labelPattern.match(text)).hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), addressFormat); + setFormat(match.capturedStart(2), match.capturedLength(2), symbolFormat); + } else if ((match = instructionPattern.match(text)).hasMatch()) { + setFormat(match.capturedStart(1), match.capturedLength(1), addressFormat); + setFormat(match.capturedStart(2), match.capturedLength(2), watchRFormat); + setFormat(match.capturedStart(3), match.capturedLength(3), watchWFormat); + setFormat(match.capturedStart(4), match.capturedLength(4), breakPFormat); + setFormat(match.capturedStart(5), match.capturedLength(5), bytesFormat); + setFormat(match.capturedStart(6), match.capturedLength(6), mnemonicFormat); + foreach(const HighlightingRule &rule, highlightingRules) { + QRegularExpressionMatchIterator iter = rule.pattern.globalMatch(text, match.capturedEnd()); + while (iter.hasNext()) { + const auto& innerMatch = iter.next(); + if (innerMatch.hasMatch()) { + setFormat(innerMatch.capturedStart(), innerMatch.capturedLength(), rule.format); + } + } + } + } +} diff --git a/gui/qt/datawidget.h b/gui/qt/datawidget.h index eedc3f700..16d07e53d 100644 --- a/gui/qt/datawidget.h +++ b/gui/qt/datawidget.h @@ -2,6 +2,9 @@ #define CODEEDITOR_H #include +#include +#include +#include #include QT_BEGIN_NAMESPACE @@ -11,6 +14,40 @@ QT_BEGIN_NAMESPACE class QWidget; QT_END_NAMESPACE +class AsmHighlighter : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + AsmHighlighter(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) Q_DECL_OVERRIDE; + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QTextCharFormat addressFormat; + QTextCharFormat symbolFormat; + QTextCharFormat watchRFormat; + QTextCharFormat watchWFormat; + QTextCharFormat breakPFormat; + QTextCharFormat bytesFormat; + QTextCharFormat mnemonicFormat; + QTextCharFormat hexFormat; + QTextCharFormat decimalFormat; + QTextCharFormat parenFormat; + QTextCharFormat registerFormat; + + QRegularExpression labelPattern; + QRegularExpression instructionPattern; +}; + class DataWidget : public QPlainTextEdit { Q_OBJECT @@ -31,6 +68,7 @@ class DataWidget : public QPlainTextEdit { private: bool moveable; + AsmHighlighter *highlighter; QList highlights; }; diff --git a/gui/qt/debugger/disasm.cpp b/gui/qt/debugger/disasm.cpp index 2ccf6f2a3..87c85fa89 100644 --- a/gui/qt/debugger/disasm.cpp +++ b/gui/qt/debugger/disasm.cpp @@ -23,11 +23,7 @@ static std::string strW(uint32_t data) { if (high) { range = disasm.map.equal_range(data); for (sit = range.first; sit != range.second; ++sit) { - if (disasm.bold_sym) { - ret += "" + sit->second + ""; - } else { - ret += sit->second; - } + ret += sit->second; ret += '|'; } if (!ret.empty()) { @@ -37,11 +33,7 @@ static std::string strW(uint32_t data) { if (!disasm.il) { range = disasm.map.equal_range(cpu.registers.MBASE<<16|data); for (sit = range.first; sit != range.second; ++sit) { - if (disasm.bold_sym) { - ret += "" + sit->second + ""; - } else { - ret += sit->second; - } + ret += sit->second; ret += '|'; } if (!ret.empty()) { @@ -67,11 +59,7 @@ static std::string strA(uint32_t data) { if (!ret.empty()) { ret += '|'; } - if (disasm.bold_sym) { - ret += "" + sit->second + ""; - } else { - ret += sit->second; - } + ret += sit->second; } } if (!ret.empty()) { @@ -86,11 +74,7 @@ static std::string strA(uint32_t data) { if (!ret.empty()) { ret += '|'; } - if (disasm.bold_sym) { - ret += "" + sit->second + ""; - } else { - ret += sit->second; - } + ret += sit->second; } } if (!ret.empty()) { diff --git a/gui/qt/mainwindow.cpp b/gui/qt/mainwindow.cpp index f8764cd5d..1996d3b40 100644 --- a/gui/qt/mainwindow.cpp +++ b/gui/qt/mainwindow.cpp @@ -886,7 +886,6 @@ void MainWindow::darkModeSwitch(bool darkMode) { #ifdef Q_OS_WIN QApplication::setStyle(darkMode ? "fusion" : "windowsvista"); #endif - m_disasmOpcodeColor = darkMode ? "darkorange" : "darkblue"; if (darkMode) { m_cBack.setColor(QPalette::Base, QColor(Qt::blue).lighter(180)); m_cBack.setColor(QPalette::Text, Qt::black); @@ -2389,15 +2388,14 @@ void MainWindow::disasmLine() { QString line; QString symbols; - QString highlighted; if (useLabel) { if (disasm.base > 511 || (disasm.base < 512 && sit->second[0] == '_')) { - line = QString(QStringLiteral("
%1     %2
")) - .arg(int2hex(static_cast(disasm.base), 6), - QString::fromStdString(disasm.bold_sym ? "" + sit->second + "" : sit->second) + ":"); + line = QStringLiteral("%1 %2:") + .arg(disasm.addr ? int2hex(static_cast(disasm.base), 6) : QString(), + QString::fromStdString(sit->second)); - m_disasm->appendHtml(line); + m_disasm->appendPlainText(line); } if (numLines == j + 1) { @@ -2405,25 +2403,16 @@ void MainWindow::disasmLine() { } sit++; } else { - symbols = QString(QStringLiteral("%1%2%3")) - .arg((disasm.highlight.watchR ? QStringLiteral("R") : QStringLiteral(" ")), - (disasm.highlight.watchW ? QStringLiteral("W") : QStringLiteral(" ")), - (disasm.highlight.breakP ? QStringLiteral("X") : QStringLiteral(" "))); - - highlighted = QString::fromStdString(disasm.instr.operands) - .replace(QRegularExpression(QStringLiteral("(\\$[0-9a-fA-F]+)")), QStringLiteral("\\1")) // hex numbers - .replace(QRegularExpression(QStringLiteral("(^\\d)")), QStringLiteral("\\1")) // dec number - .replace(QRegularExpression(QStringLiteral("([()])")), QStringLiteral("\\1")); // parentheses - - line = QString(QStringLiteral("
%1 %2 %3  %5 %6
")) + line = QString(QStringLiteral("%1 %2%3%4 %5 %6 %7")) .arg(disasm.addr ? int2hex(static_cast(disasm.base), 6) : QString(), - symbols, + disasm.highlight.watchR ? QStringLiteral("R") : QStringLiteral(" "), + disasm.highlight.watchW ? QStringLiteral("W") : QStringLiteral(" "), + disasm.highlight.breakP ? QStringLiteral("X") : QStringLiteral(" "), disasm.bytes ? QString::fromStdString(disasm.instr.data).leftJustified(12, ' ') : QStringLiteral(" "), - m_disasmOpcodeColor, QString::fromStdString(disasm.instr.opcode), - highlighted); + QString::fromStdString(disasm.instr.operands)); - m_disasm->appendHtml(line); + m_disasm->appendPlainText(line); } } diff --git a/gui/qt/mainwindow.h b/gui/qt/mainwindow.h index 7350c641f..d8016e167 100644 --- a/gui/qt/mainwindow.h +++ b/gui/qt/mainwindow.h @@ -573,7 +573,6 @@ class MainWindow : public QMainWindow { InterCom com; bool m_isInDarkMode = false; - const char* m_disasmOpcodeColor; int m_watchGUIMask = DBG_MASK_NONE;