kde-workspace/drkonqi/gdbhighlighter.cpp
2014-11-15 04:16:00 +02:00

141 lines
5.7 KiB
C++

/*
Copyright (C) 2010 Milian Wolff <mail@milianw.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "gdbhighlighter.h"
#include <QTextDocument>
#include <KColorScheme>
GdbHighlighter::GdbHighlighter(QTextDocument* parent, const QList<BacktraceLine> & gdbLines)
: QSyntaxHighlighter(parent)
{
// setup line lookup
int l = 0;
foreach(const BacktraceLine& line, gdbLines) {
lines.insert(l, line);
l += line.toString().count('\n');
}
// Add a dummy, in case the last backtrace line has more than 1 '\n' char.
const BacktraceLine dummy;
lines.insert(l, dummy);
// setup formates
KColorScheme scheme(QPalette::Active);
crashFormat.setForeground(scheme.foreground(KColorScheme::NegativeText));
nullptrFormat.setForeground(scheme.foreground(KColorScheme::NegativeText));
nullptrFormat.setFontWeight(QFont::Bold);
assertFormat = nullptrFormat;
threadFormat.setForeground(scheme.foreground(KColorScheme::NeutralText));
urlFormat.setForeground(scheme.foreground(KColorScheme::LinkText));
funcFormat.setForeground(scheme.foreground(KColorScheme::VisitedText));
funcFormat.setFontWeight(QFont::Bold);
otheridFormat.setForeground(scheme.foreground(KColorScheme::PositiveText));
crapFormat.setForeground(scheme.foreground(KColorScheme::InactiveText));
}
void GdbHighlighter::highlightBlock(const QString& text)
{
int cur = 0;
int next;
int diff;
const QRegExp hexptrPattern("0x[0-9a-f]+", Qt::CaseSensitive, QRegExp::RegExp2);
int lineNr = currentBlock().firstLineNumber();
while ( cur < text.length() ) {
next = text.indexOf('\n', cur);
if (next == -1) {
next = text.length();
}
if (lineNr == 0) {
// line that contains 'Application: ...'
++lineNr;
cur = next;
continue;
}
diff = next - cur;
QString lineStr = text.mid(cur, diff).append('\n');
// -1 since we skip the first line
QMap< int, BacktraceLine >::iterator it = lines.lowerBound(lineNr - 1);
Q_ASSERT(it != lines.end());
// QMap::lowerBound() returns the next higher item or
// the dummy item, but we want the one before that.
if (it.key() > lineNr - 1) {
--it;
}
const BacktraceLine& line = it.value();
if (line.type() == BacktraceLine::KCrash) {
setFormat(cur, diff, crashFormat);
} else if (line.type() == BacktraceLine::ThreadStart || line.type() == BacktraceLine::ThreadIndicator) {
setFormat(cur, diff, threadFormat);
} else if (line.type() == BacktraceLine::Crap) {
setFormat(cur, diff, crapFormat);
} else if (line.type() == BacktraceLine::StackFrame) {
if (!line.fileName().isEmpty()) {
int colonPos = line.fileName().lastIndexOf(':');
setFormat(lineStr.indexOf(line.fileName()), colonPos == -1 ? line.fileName().length() : colonPos, urlFormat);
}
if (!line.libraryName().isEmpty()) {
setFormat(lineStr.indexOf(line.libraryName()), line.libraryName().length(), urlFormat);
}
if (!line.functionName().isEmpty()) {
int idx = lineStr.indexOf(line.functionName());
if (idx != -1) {
// highlight Id::Id::Id::Func
// Id should have otheridFormat, :: no format and Func funcFormat
int i = idx;
int from = idx;
while (i < idx + line.functionName().length()) {
if (lineStr.at(i) == ':') {
setFormat(from, i - from, otheridFormat);
// skip ::
i += 2;
from = i;
continue;
} else if (lineStr.at(i) == '<' || lineStr.at(i) == '>') {
setFormat(from, i - from, otheridFormat);
++i;
from = i;
continue;
}
++i;
}
if (line.functionName() == "qFatal" || line.functionName() == "abort" || line.functionName() == "__assert_fail"
|| line.functionName() == "*__GI___assert_fail" || line.functionName() == "*__GI_abort") {
setFormat(from, i - from, assertFormat);
} else {
setFormat(from, i - from, funcFormat);
}
}
}
// highlight hexadecimal ptrs
int idx = 0;
while ((idx = hexptrPattern.indexIn(lineStr, idx)) != -1) {
if (hexptrPattern.cap() == "0x0") {
setFormat(idx, hexptrPattern.matchedLength(), nullptrFormat);
}
idx += hexptrPattern.matchedLength();
}
}
cur = next;
++lineNr;
}
}