Debugger: Use syntax highlight info for source code view.
SourceView: - Request syntax highlight information when new source file is set. - Adjust _FormatLine() to also patch raw syntax highlights to match up with calculated tabstops. - Draw strings in pieces corresponding to how they're broken up in terms of syntax highlights with colors.
This commit is contained in:
@@ -41,6 +41,7 @@
|
|||||||
#include "SourceLanguage.h"
|
#include "SourceLanguage.h"
|
||||||
#include "StackTrace.h"
|
#include "StackTrace.h"
|
||||||
#include "Statement.h"
|
#include "Statement.h"
|
||||||
|
#include "SyntaxHighlighter.h"
|
||||||
#include "Team.h"
|
#include "Team.h"
|
||||||
#include "Tracing.h"
|
#include "Tracing.h"
|
||||||
|
|
||||||
@@ -49,6 +50,9 @@ static const int32 kLeftTextMargin = 3;
|
|||||||
static const float kMinViewHeight = 80.0f;
|
static const float kMinViewHeight = 80.0f;
|
||||||
static const int32 kSpacesPerTab = 4;
|
static const int32 kSpacesPerTab = 4;
|
||||||
// TODO: Should be settable!
|
// TODO: Should be settable!
|
||||||
|
|
||||||
|
static const int32 kMaxHighlightsPerLine = 64;
|
||||||
|
|
||||||
static const bigtime_t kScrollTimer = 10000LL;
|
static const bigtime_t kScrollTimer = 10000LL;
|
||||||
|
|
||||||
static const char* kClearBreakpointMessage = "Click to clear breakpoint at "
|
static const char* kClearBreakpointMessage = "Click to clear breakpoint at "
|
||||||
@@ -64,6 +68,21 @@ static const uint32 MSG_SWITCH_DISASSEMBLY_STATE = 'msds';
|
|||||||
static const char* kTrackerSignature = "application/x-vnd.Be-TRAK";
|
static const char* kTrackerSignature = "application/x-vnd.Be-TRAK";
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: make configurable.
|
||||||
|
// Current values taken from Pe's defaults.
|
||||||
|
static rgb_color kSyntaxColors[] = {
|
||||||
|
{0, 0, 0, 255}, // SYNTAX_HIGHLIGHT_NONE
|
||||||
|
{0x39, 0x74, 0x79, 255}, // SYNTAX_HIGHLIGHT_KEYWORD
|
||||||
|
{0, 0x64, 0, 255}, // SYNTAX_HIGHLIGHT_PREPROCESSOR_KEYWORD
|
||||||
|
{0, 0, 0, 255}, // SYNTAX_HIGHLIGHT_IDENTIFIER
|
||||||
|
{0x44, 0x8a, 0, 255}, // SYNTAX_HIGHLIGHT_OPERATOR
|
||||||
|
{0, 0, 0, 255}, // SYNTAX_HIGHLIGHT_TYPE
|
||||||
|
{0x85, 0x19, 0x19, 255}, // SYNTAX_HIGHLIGHT_NUMERIC_LITERAL
|
||||||
|
{0x85, 0x19, 0x19, 255}, // SYNTAX_HIGHLIGHT_STRING_LITERAL
|
||||||
|
{0xa1, 0x64, 0xe, 255}, // SYNTAX_HIGHLIGHT_COMMENT
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class SourceView::BaseView : public BView {
|
class SourceView::BaseView : public BView {
|
||||||
public:
|
public:
|
||||||
BaseView(const char* name,
|
BaseView(const char* name,
|
||||||
@@ -312,7 +331,8 @@ private:
|
|||||||
|
|
||||||
float _MaxLineWidth();
|
float _MaxLineWidth();
|
||||||
void _FormatLine(const char* line,
|
void _FormatLine(const char* line,
|
||||||
BString& formattedLine);
|
BString& formattedLine,
|
||||||
|
int32* columns, int32 columnCount);
|
||||||
inline int32 _NextTabStop(int32 column) const;
|
inline int32 _NextTabStop(int32 column) const;
|
||||||
float _FormattedPosition(int32 line,
|
float _FormattedPosition(int32 line,
|
||||||
int32 offset) const;
|
int32 offset) const;
|
||||||
@@ -1144,11 +1164,23 @@ SourceView::TextView::Draw(BRect updateRect)
|
|||||||
SourceView::MarkerManager::InstructionPointerMarker* ipMarker;
|
SourceView::MarkerManager::InstructionPointerMarker* ipMarker;
|
||||||
int32 markerIndex = 0;
|
int32 markerIndex = 0;
|
||||||
float y;
|
float y;
|
||||||
|
|
||||||
|
// syntax line data
|
||||||
|
int32 columns[kMaxHighlightsPerLine];
|
||||||
|
syntax_highlight_type types[kMaxHighlightsPerLine];
|
||||||
|
SyntaxHighlightInfo* info = fSourceView->fCurrentSyntaxInfo;
|
||||||
|
|
||||||
for (int32 i = minLine; i <= maxLine; i++) {
|
for (int32 i = minLine; i <= maxLine; i++) {
|
||||||
|
int32 syntaxCount = 0;
|
||||||
|
if (info != NULL) {
|
||||||
|
syntaxCount = info->GetLineHighlightRanges(i, columns, types,
|
||||||
|
kMaxHighlightsPerLine);
|
||||||
|
}
|
||||||
|
|
||||||
SetLowColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
SetLowColor(ui_color(B_DOCUMENT_BACKGROUND_COLOR));
|
||||||
y = i * fFontInfo->lineHeight;
|
y = i * fFontInfo->lineHeight;
|
||||||
BString lineString;
|
BString lineString;
|
||||||
_FormatLine(fSourceCode->LineAt(i), lineString);
|
_FormatLine(fSourceCode->LineAt(i), lineString, columns, syntaxCount);
|
||||||
|
|
||||||
FillRect(BRect(0.0, y, kLeftTextMargin, y + fFontInfo->lineHeight),
|
FillRect(BRect(0.0, y, kLeftTextMargin, y + fFontInfo->lineHeight),
|
||||||
B_SOLID_LOW);
|
B_SOLID_LOW);
|
||||||
@@ -1176,8 +1208,28 @@ SourceView::TextView::Draw(BRect updateRect)
|
|||||||
|
|
||||||
FillRect(BRect(kLeftTextMargin, y, Bounds().right,
|
FillRect(BRect(kLeftTextMargin, y, Bounds().right,
|
||||||
y + fFontInfo->lineHeight - 1), B_SOLID_LOW);
|
y + fFontInfo->lineHeight - 1), B_SOLID_LOW);
|
||||||
DrawString(lineString,
|
syntax_highlight_type currentHighlight = SYNTAX_HIGHLIGHT_NONE;
|
||||||
BPoint(kLeftTextMargin, y + fFontInfo->fontHeight.ascent));
|
int32 currentColumn = 0;
|
||||||
|
SetHighColor(kSyntaxColors[currentHighlight]);
|
||||||
|
BPoint linePoint(kLeftTextMargin, y + fFontInfo->fontHeight.ascent);
|
||||||
|
for (int32 j = 0; j < syntaxCount; j++) {
|
||||||
|
int32 length = columns[j] - currentColumn;
|
||||||
|
if (length != 0) {
|
||||||
|
DrawString(lineString.String() + currentColumn, length,
|
||||||
|
linePoint);
|
||||||
|
currentColumn += length;
|
||||||
|
linePoint.x += fCharacterWidth * length;
|
||||||
|
|
||||||
|
}
|
||||||
|
currentHighlight = types[j];
|
||||||
|
SetHighColor(kSyntaxColors[currentHighlight]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw remainder, if any.
|
||||||
|
if (currentColumn < lineString.Length()) {
|
||||||
|
DrawString(lineString.String() + currentColumn, lineString.Length()
|
||||||
|
- currentColumn, linePoint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y = (maxLine + 1) * fFontInfo->lineHeight;
|
y = (maxLine + 1) * fFontInfo->lineHeight;
|
||||||
@@ -1480,20 +1532,33 @@ SourceView::TextView::_MaxLineWidth()
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourceView::TextView::_FormatLine(const char* line, BString& formattedLine)
|
SourceView::TextView::_FormatLine(const char* line, BString& formattedLine,
|
||||||
|
int32* columns, int32 columnCount)
|
||||||
{
|
{
|
||||||
int32 column = 0;
|
int32 column = 0;
|
||||||
for (; *line != '\0'; line++) {
|
int32 columnAdjustments[columnCount];
|
||||||
|
memset(columnAdjustments, 0, sizeof(columnAdjustments));
|
||||||
|
for (int32 i = 0; line[i] != '\0'; i++) {
|
||||||
// TODO: That's probably not very efficient!
|
// TODO: That's probably not very efficient!
|
||||||
if (*line == '\t') {
|
if (line[i] == '\t') {
|
||||||
int32 nextTabStop = _NextTabStop(column);
|
int32 nextTabStop = _NextTabStop(column);
|
||||||
|
int32 diff = nextTabStop - column;
|
||||||
for (; column < nextTabStop; column++)
|
for (; column < nextTabStop; column++)
|
||||||
formattedLine << ' ';
|
formattedLine << ' ';
|
||||||
|
for (int32 j = 0; j < columnCount; j++) {
|
||||||
|
// syntax highlights need to be offset according
|
||||||
|
// to our tabstop adjustments as well.
|
||||||
|
if (columns[j] >= i && diff > 0)
|
||||||
|
columnAdjustments[j] += (diff - 1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
formattedLine << *line;
|
formattedLine << line[i];
|
||||||
column++;
|
column++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0; i < columnCount; i++)
|
||||||
|
columns[i] += columnAdjustments[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1945,7 +2010,8 @@ SourceView::SourceView(Team* team, Listener* listener)
|
|||||||
fSourceCode(NULL),
|
fSourceCode(NULL),
|
||||||
fMarkerView(NULL),
|
fMarkerView(NULL),
|
||||||
fTextView(NULL),
|
fTextView(NULL),
|
||||||
fListener(listener)
|
fListener(listener),
|
||||||
|
fCurrentSyntaxInfo(NULL)
|
||||||
{
|
{
|
||||||
// init font info
|
// init font info
|
||||||
fFontInfo.font = *be_fixed_font;
|
fFontInfo.font = *be_fixed_font;
|
||||||
@@ -2148,13 +2214,26 @@ SourceView::SetSourceCode(SourceCode* sourceCode)
|
|||||||
fTextView->SetSourceCode(NULL);
|
fTextView->SetSourceCode(NULL);
|
||||||
fMarkerView->SetSourceCode(NULL);
|
fMarkerView->SetSourceCode(NULL);
|
||||||
fSourceCode->ReleaseReference();
|
fSourceCode->ReleaseReference();
|
||||||
|
delete fCurrentSyntaxInfo;
|
||||||
|
fCurrentSyntaxInfo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
fSourceCode = sourceCode;
|
fSourceCode = sourceCode;
|
||||||
|
|
||||||
if (fSourceCode != NULL)
|
if (fSourceCode != NULL) {
|
||||||
fSourceCode->AcquireReference();
|
fSourceCode->AcquireReference();
|
||||||
|
|
||||||
|
SourceLanguage* language = fSourceCode->GetSourceLanguage();
|
||||||
|
if (language != NULL) {
|
||||||
|
SyntaxHighlighter* highlighter = language->GetSyntaxHighlighter();
|
||||||
|
if (highlighter != NULL) {
|
||||||
|
BReference<SyntaxHighlighter> syntaxReference(highlighter,
|
||||||
|
true);
|
||||||
|
highlighter->ParseText(fSourceCode, fCurrentSyntaxInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fMarkerManager->SetSourceCode(fSourceCode);
|
fMarkerManager->SetSourceCode(fSourceCode);
|
||||||
fTextView->SetSourceCode(fSourceCode);
|
fTextView->SetSourceCode(fSourceCode);
|
||||||
fMarkerView->SetSourceCode(fSourceCode);
|
fMarkerView->SetSourceCode(fSourceCode);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class SourceCode;
|
|||||||
class StackFrame;
|
class StackFrame;
|
||||||
class StackTrace;
|
class StackTrace;
|
||||||
class Statement;
|
class Statement;
|
||||||
|
class SyntaxHighlightInfo;
|
||||||
class Team;
|
class Team;
|
||||||
class Thread;
|
class Thread;
|
||||||
class UserBreakpoint;
|
class UserBreakpoint;
|
||||||
@@ -95,6 +96,7 @@ private:
|
|||||||
TextView* fTextView;
|
TextView* fTextView;
|
||||||
FontInfo fFontInfo;
|
FontInfo fFontInfo;
|
||||||
Listener* fListener;
|
Listener* fListener;
|
||||||
|
SyntaxHighlightInfo* fCurrentSyntaxInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user