diff --git a/RedPandaIDE/qsynedit/SynEdit.cpp b/RedPandaIDE/qsynedit/SynEdit.cpp
index c4356e54..3085b398 100644
--- a/RedPandaIDE/qsynedit/SynEdit.cpp
+++ b/RedPandaIDE/qsynedit/SynEdit.cpp
@@ -325,19 +325,8 @@ DisplayCoord SynEdit::pixelsToRowColumn(int aX, int aY)
DisplayCoord SynEdit::bufferToDisplayPos(const BufferCoord &p)
{
DisplayCoord result {p.Char,p.Line};
- // Account for tabs
- if (p.Line-1 < mLines->count()) {
- QString s = mLines->getString(p.Line - 1);
- int l = s.length();
- int x = 0;
- for (int i=0;i
count()) {
+ QString s = mLines->getString(aLine - 1);
+ int l = s.length();
+ int x = 0;
+ for (int i=0;i0)
diff --git a/RedPandaIDE/qsynedit/SynEdit.h b/RedPandaIDE/qsynedit/SynEdit.h
index 15ecfec3..1b8c6a56 100644
--- a/RedPandaIDE/qsynedit/SynEdit.h
+++ b/RedPandaIDE/qsynedit/SynEdit.h
@@ -162,6 +162,8 @@ public:
DisplayCoord pixelsToRowColumn(int aX, int aY);
DisplayCoord bufferToDisplayPos(const BufferCoord& p);
BufferCoord displayToBufferPos(const DisplayCoord& p);
+ int charToColumn(int aLine, int aChar);
+ int stringColumns(const QString& line);
int rowToLine(int aRow);
int lineToRow(int aLine);
int foldRowToLine(int Row);
@@ -212,6 +214,8 @@ public:
int maxScrollWidth() const;
void setMaxScrollWidth(int Value);
+ int tabWidth() const;
+
signals:
void Changed();
@@ -234,6 +238,9 @@ signals:
void scrolled(SynScrollBarKind ScrollBar);
void statusChanged(SynStatusChanges changes);
+ void fontChanged();
+ void tabSizeChanged();
+
private:
void clearAreaList(SynEditingAreaList areaList);
void computeCaret(int X, int Y);
@@ -411,4 +418,6 @@ protected:
friend class SynEditTextPainter;
};
+class
+
#endif // SYNEDIT_H
diff --git a/RedPandaIDE/qsynedit/TextBuffer.cpp b/RedPandaIDE/qsynedit/TextBuffer.cpp
index 39423f1e..54dfe4d8 100644
--- a/RedPandaIDE/qsynedit/TextBuffer.cpp
+++ b/RedPandaIDE/qsynedit/TextBuffer.cpp
@@ -4,22 +4,25 @@
#include
#include
#include
+#include "SynEdit.h"
#include "../utils.h"
-SynEditStringList::SynEditStringList(QObject* parent):
- QObject(parent)
+SynEditStringList::SynEditStringList(SynEdit *pEdit, QObject *parent):
+ QObject(parent),
+ mEdit(pEdit)
{
mAppendNewLineAtEOF = true;
mFileEndingType = FileEndingType::Windows;
mIndexOfLongestLine = -1;
mUpdateCount = 0;
- setTabWidth(8);
}
static void ListIndexOutOfBounds(int index) {
throw IndexOutOfRange(index);
}
+
+
int SynEditStringList::parenthesisLevels(int Index)
{
if (Index>=0 && Index < mList.size()) {
@@ -44,24 +47,24 @@ int SynEditStringList::braceLevels(int Index)
return 0;
}
-QString SynEditStringList::expandedStrings(int Index)
-{
- if (Index>=0 && Index < mList.size()) {
- if (mList[Index]->fFlags & SynEditStringFlag::sfHasNoTabs)
- return mList[Index]->fString;
- else
- return ExpandString(Index);
- } else
- return QString();
-}
+//QString SynEditStringList::expandedStrings(int Index)
+//{
+// if (Index>=0 && Index < mList.size()) {
+// if (mList[Index]->fFlags & SynEditStringFlag::sfHasNoTabs)
+// return mList[Index]->fString;
+// else
+// return ExpandString(Index);
+// } else
+// return QString();
+//}
-int SynEditStringList::expandedStringLength(int Index)
+int SynEditStringList::lineColumns(int Index)
{
if (Index>=0 && Index < mList.size()) {
- if (mList[Index]->fFlags & sfExpandedLengthUnknown)
- return ExpandString(Index).length();
- else
- return mList[Index]->fExpandedLength;
+ if (mList[Index]->fColumns == -1) {
+ return calculateLineColumns(Index);
+ } else
+ return mList[Index]->fColumns;
} else
return 0;
}
@@ -73,7 +76,7 @@ int SynEditStringList::lengthOfLongestLine()
mIndexOfLongestLine = -1;
if (mList.count() > 0 ) {
for (int i=0;i MaxLen) {
MaxLen = len;
mIndexOfLongestLine = i;
@@ -82,7 +85,7 @@ int SynEditStringList::lengthOfLongestLine()
}
}
if (mIndexOfLongestLine >= 0)
- return mList[mIndexOfLongestLine]->fExpandedLength;
+ return mList[mIndexOfLongestLine]->fColumns;
else
return 0;
}
@@ -207,23 +210,6 @@ void SynEditStringList::endUpdate()
}
}
-int SynEditStringList::tabWidth()
-{
- return mTabWidth;
-}
-
-void SynEditStringList::setTabWidth(int value)
-{
- if (value != mTabWidth) {
- mTabWidth = value;
- mConvertTabsProc = GetBestConvertTabsProcEx(mTabWidth);
- mIndexOfLongestLine = -1;
- for (PSynEditStringRec& line:mList) {
- line->fExpandedLength = -1;
- line->fFlags = SynEditStringFlag::sfExpandedLengthUnknown;
- }
- }
-}
int SynEditStringList::add(const QString &s)
{
@@ -365,7 +351,6 @@ void SynEditStringList::putString(int Index, const QString &s) {
}
beginUpdate();
mIndexOfLongestLine = -1;
- mList[Index]->fFlags = SynEditStringFlag::sfExpandedLengthUnknown;
mList[Index]->fString = s;
emit putted(Index,1);
endUpdate();
@@ -390,24 +375,12 @@ void SynEditStringList::SetUpdateState(bool Updating)
emit changed();
}
-QString SynEditStringList::ExpandString(int Index)
+int SynEditStringList::calculateLineColumns(int Index)
{
- QString Result("");
PSynEditStringRec line = mList[Index];
- if (line->fString.isEmpty()) {
- line->fFlags = SynEditStringFlag::sfHasNoTabs;
- line->fExpandedLength = 0;
- } else {
- bool hasTabs;
- Result = mConvertTabsProc(line->fString,mTabWidth,hasTabs);
- line->fExpandedLength = Result.length();
- if (hasTabs) {
- line->fFlags = SynEditStringFlag::sfHasTabs;
- } else {
- line->fFlags = SynEditStringFlag::sfHasNoTabs;
- }
- }
- return Result;
+
+ line->fColumns = mEdit->stringColumns(line->fString);
+ return line->fColumns;
}
void SynEditStringList::InsertLines(int Index, int NumLines)
@@ -619,15 +592,22 @@ void SynEditStringList::setFileEndingType(const FileEndingType &fileEndingType)
mFileEndingType = fileEndingType;
}
+void SynEditStringList::invalidAllLineColumns()
+{
+ mIndexOfLongestLine = -1;
+ for (PSynEditStringRec& line:mList) {
+ line->fColumns = -1;
+ }
+}
+
SynEditStringRec::SynEditStringRec():
fString(),
fObject(nullptr),
fRange{0,0},
- fExpandedLength(-1),
+ fColumns(-1),
fParenthesisLevel(0),
fBracketLevel(0),
- fBraceLevel(0),
- fFlags(SynEditStringFlag::sfExpandedLengthUnknown)
+ fBraceLevel(0)
{
}
diff --git a/RedPandaIDE/qsynedit/TextBuffer.h b/RedPandaIDE/qsynedit/TextBuffer.h
index 1542c0a2..7ab67e3e 100644
--- a/RedPandaIDE/qsynedit/TextBuffer.h
+++ b/RedPandaIDE/qsynedit/TextBuffer.h
@@ -21,8 +21,7 @@ struct SynEditStringRec {
QString fString;
void * fObject;
SynRangeState fRange;
- int fExpandedLength;
- SynEditStringFlags fFlags;
+ int fColumns; //
int fParenthesisLevel;
int fBracketLevel;
int fBraceLevel;
@@ -44,17 +43,18 @@ typedef std::shared_ptr PSynEditStringList;
using StringListChangeCallback = std::function;
class QFile;
+
+class SynEdit;
class SynEditStringList : public QObject
{
Q_OBJECT
public:
- explicit SynEditStringList(QObject* parent=nullptr);
+ explicit SynEditStringList(SynEdit* pEdit,QObject* parent=nullptr);
int parenthesisLevels(int Index);
int bracketLevels(int Index);
int braceLevels(int Index);
- QString expandedStrings(int Index);
- int expandedStringLength(int Index);
+ int lineColumns(int Index);
int lengthOfLongestLine();
SynRangeState ranges(int Index);
void setRange(int Index, SynRangeState ARange);
@@ -73,8 +73,6 @@ public:
void beginUpdate();
void endUpdate();
- int tabWidth();
- void setTabWidth(int value);
int add(const QString& s);
int addStrings(const QStringList& Strings);
@@ -97,6 +95,8 @@ public:
FileEndingType getFileEndingType() const;
void setFileEndingType(const FileEndingType &fileEndingType);
+public slots:
+ void invalidAllLineColumns();
signals:
void changed();
@@ -114,16 +114,16 @@ protected:
private:
SynEditStringRecList mList;
+ SynEdit* mEdit;
//int mCount;
//int mCapacity;
FileEndingType mFileEndingType;
bool mAppendNewLineAtEOF;
ConvertTabsProcEx mConvertTabsProc;
int mIndexOfLongestLine;
- int mTabWidth;
int mUpdateCount;
- QString ExpandString(int Index);
+ int calculateLineColumns(int Index);
};
enum class SynChangeReason {crInsert, crPaste, crDragDropInsert,
diff --git a/RedPandaIDE/qsynedit/TextPainter.cpp b/RedPandaIDE/qsynedit/TextPainter.cpp
index c6111294..4c2491de 100644
--- a/RedPandaIDE/qsynedit/TextPainter.cpp
+++ b/RedPandaIDE/qsynedit/TextPainter.cpp
@@ -302,7 +302,8 @@ bool SynEditTextPainter::TokenIsSpaces(bool &bSpacesTest, const QString& Token,
// Store the token chars with the attributes in the TokenAccu
// record. This will paint any chars already stored if there is
// a (visible) change in the attributes.
-void SynEditTextPainter::AddHighlightToken(const QString &Token, int ColumnsBefore, int TokenColumns, int cLine, PSynHighlighterAttribute p_Attri)
+void SynEditTextPainter::AddHighlightToken(const QString &Token, int ColumnsBefore,
+ int TokenColumns, int cLine, PSynHighlighterAttribute p_Attri)
{
bool bCanAppend;
QColor Foreground, Background;
@@ -463,240 +464,213 @@ void SynEditTextPainter::PaintLines()
// inside the loop. Get only the starting point for this.
rcLine = AClip;
rcLine.setBottom((aFirstRow - edit->mTopLine) * edit->mTextHeight);
- // Make sure the token accumulator string doesn't get reassigned too often.
TokenAccu.Columns = 0;
TokenAccu.ColumnsBefore = 0;
- if (fHighlighter) then begin
- TokenAccu.MaxLen := Max(128, fCharsInWindow);
- SetLength(TokenAccu.s, TokenAccu.MaxLen);
- end;
// Now loop through all the lines. The indices are valid for Lines.
- for cRow := aFirstRow to aLastRow do begin
- vLine := RowToLine(cRow);
- if (vLine > Lines.Count) and not (Lines.Count = 0) then
- break;
+ for (cRow = aFirstRow; cRow<=aLastRow; cRow++) {
+ vLine = edit->rowToLine(cRow);
+ if (vLine > edit->mLines->count() && edit->mLines->count() != 0)
+ break;
- // Get the expanded line.
- sLine := Lines.ExpandedStrings[vLine - 1];
- // determine whether will be painted with ActiveLineColor
- bCurrentLine := CaretY = vLine;
- // Initialize the text and background colors, maybe the line should
- // use special values for them.
- colFG := Font.Color;
- colBG := colEditorBG;
- bSpecialLine := DoOnSpecialLineColors(vLine, colFG, colBG);
- if bSpecialLine then begin
- // The selection colors are just swapped, like seen in Delphi.
- colSelFG := colBG;
- colSelBG := colFG;
- end else begin
- colSelFG := fSelectedColor.Foreground;
- colSelBG := fSelectedColor.Background;
- DoOnEditAreas(vLine, areaList,colBorder,areaType);
- end;
-
- // Removed word wrap support
- vFirstChar := FirstCol;
- vLastChar := LastCol;
-
- // Get the information about the line selection. Three different parts
- // are possible (unselected before, selected, unselected after), only
- // unselected or only selected means bComplexLine will be FALSE. Start
- // with no selection, compute based on the visible columns.
- bComplexLine := FALSE;
- nLineSelStart := 0;
- nLineSelEnd := 0;
- // Does the selection intersect the visible area?
- if bAnySelection and (cRow >= vSelStart.Row) and (cRow <= vSelEnd.Row) then begin
- // Default to a fully selected line. This is correct for the smLine
- // selection mode and a good start for the smNormal mode.
- nLineSelStart := FirstCol;
- nLineSelEnd := LastCol + 1;
- if (fActiveSelectionMode = smColumn) or
- ((fActiveSelectionMode = smNormal) and (cRow = vSelStart.Row)) then
- if (vSelStart.Column > LastCol) then begin
- nLineSelStart := 0;
- nLineSelEnd := 0;
- end else if (vSelStart.Column > FirstCol) then begin
- nLineSelStart := vSelStart.Column;
- bComplexLine := TRUE;
- end;
- if (fActiveSelectionMode = smColumn) or
- ((fActiveSelectionMode = smNormal) and (cRow = vSelEnd.Row)) then
- if (vSelEnd.Column < FirstCol) then begin
- nLineSelStart := 0;
- nLineSelEnd := 0;
- end else if (vSelEnd.Column < LastCol) then begin
- nLineSelEnd := vSelEnd.Column;
- bComplexLine := TRUE;
- end;
- {$IFDEF SYN_MBCSSUPPORT}
- //todo: nLineSelStart & nLineSelEnd must be buffer coordinates
- if (fActiveSelectionMode = smColumn) then
- MBCSGetSelRangeInLineWhenColumnSelectionMode(sLine, nLineSelStart,
- nLineSelEnd);
- {$ENDIF}
- end; //endif bAnySelection
-
- // Update the rcLine rect to this line.
- rcLine.Top := rcLine.Bottom;
- Inc(rcLine.Bottom, fTextHeight);
-
- bLineSelected := (not bComplexLine) and (nLineSelStart > 0);
- rcToken := rcLine;
-
- if not Assigned(fHighlighter) or (not fHighlighter.Enabled) then begin
- // Remove text already displayed (in previous rows)
- if (vFirstChar <> FirstCol) or (vLastChar <> LastCol) then
- sToken := Copy(sLine, vFirstChar, vLastChar - vFirstChar)
- else
- sToken := sLine;
- if fShowSpecChar and (not bLineSelected) and (not bSpecialLine) and (Length(sLine) < vLastChar) then
- sToken := sToken + SynLineBreakGlyph;
- nTokenLen := Length(sToken);
- if bComplexLine then begin
- SetDrawingColors(FALSE);
- rcToken.Left := Max(rcLine.Left, ColumnToXValue(FirstCol));
- rcToken.Right := Min(rcLine.Right, ColumnToXValue(nLineSelStart));
- PaintToken(sToken, nTokenLen, 0, FirstCol, nLineSelStart,False);
- rcToken.Left := Max(rcLine.Left, ColumnToXValue(nLineSelEnd));
- rcToken.Right := Min(rcLine.Right, ColumnToXValue(LastCol));
- PaintToken(sToken, nTokenLen, 0, nLineSelEnd, LastCol,True);
- SetDrawingColors(TRUE);
- rcToken.Left := Max(rcLine.Left, ColumnToXValue(nLineSelStart));
- rcToken.Right := Min(rcLine.Right, ColumnToXValue(nLineSelEnd));
- PaintToken(sToken, nTokenLen, 0, nLineSelStart, nLineSelEnd - 1,False);
- end else begin
- SetDrawingColors(bLineSelected);
- PaintToken(sToken, nTokenLen, 0, FirstCol, LastCol,bLineSelected);
- end;
- end else begin
- // Initialize highlighter with line text and range info. It is
- // necessary because we probably did not scan to the end of the last
- // line - the internal highlighter range might be wrong.
- if vLine = 1 then begin
- fHighlighter.ResetRange;
- fHighlighter.ResetParenthesisLevel;
- fHighlighter.ResetBracketLevel;
- fHighlighter.ResetBraceLevel;
- end else begin
- fHighlighter.SetRange(Lines.Ranges[vLine - 2]);
- fHighlighter.SetParenthesisLevel(Lines.ParenthesisLevels[vLine - 2]);
- fHighlighter.SetBracketLevel(Lines.BracketLevels[vLine - 2]);
- fHighlighter.SetBraceLevel(Lines.BraceLevels[vLine - 2]);
- end;
- fHighlighter.SetLine(sLine, vLine - 1);
- // Try to concatenate as many tokens as possible to minimize the count
- // of ExtTextOut calls necessary. This depends on the selection state
- // or the line having special colors. For spaces the foreground color
- // is ignored as well.
- TokenAccu.Len := 0;
- nTokenPos := 0;
- // Test first whether anything of this token is visible.
- while not fHighlighter.GetEol do begin
- sToken := fHighlighter.GetToken;
- // Work-around buggy highlighters which return empty tokens.
- if sToken = '' then begin
- fHighlighter.Next;
- if fHighlighter.GetEol then
- break;
- sToken := fHighlighter.GetToken;
- // Maybe should also test whether GetTokenPos changed...
- if sToken = '' then
- raise Exception.Create('The highlighter seems to be in an infinite loop');
- end;
- nTokenPos := fHighlighter.GetTokenPos;
- nTokenLen := Length(sToken);
- if nTokenPos + nTokenLen >= vFirstChar then begin
- if nTokenPos + nTokenLen >= vLastChar then begin
- if nTokenPos >= vLastChar then
- break; //*** BREAK ***
-
- nTokenLen := vLastChar - nTokenPos - 1;
- end;
- // It's at least partially visible. Get the token attributes now.
- attr := fHighlighter.GetTokenAttribute;
- {
- if (nTokenPos = 0) and (attr = fHighlighter.WhitespaceAttribute) then begin
- sToken := StringOfChar('.',nTokenLen);
- end;
+ // Get the line.
+ sLine = edit->mLines->getString(vLine - 1);
+ // determine whether will be painted with ActiveLineColor
+ bCurrentLine = (edit->mCaretY == vLine);
+ // Initialize the text and background colors, maybe the line should
+ // use special values for them.
+ colFG = edit->palette().color(QPalette::Text);
+ colBG = colEditorBG();
+ bSpecialLine = edit->DoOnSpecialLineColors(vLine, colFG, colBG);
+ if (bSpecialLine) {
+ // The selection colors are just swapped, like seen in Delphi.
+ colSelFG = colBG;
+ colSelBG = colFG;
+ } else {
+ colSelFG = edit->mSelectedForeground;
+ colSelBG = edit->mSelectedBackground;
+ }
+ edit->DoOnEditAreas(vLine, areaList);
+ // Removed word wrap support
+ vFirstChar = FirstCol;
+ vLastChar = LastCol;
+ // Get the information about the line selection. Three different parts
+ // are possible (unselected before, selected, unselected after), only
+ // unselected or only selected means bComplexLine will be FALSE. Start
+ // with no selection, compute based on the visible columns.
+ bComplexLine = false;
+ nLineSelStart = 0;
+ nLineSelEnd = 0;
+ // Does the selection intersect the visible area?
+ if (bAnySelection && (cRow >= vSelStart.Row) && (cRow <= vSelEnd.Row)) {
+ // Default to a fully selected line. This is correct for the smLine
+ // selection mode and a good start for the smNormal mode.
+ nLineSelStart = FirstCol;
+ nLineSelEnd = LastCol + 1;
+ if ((edit->mActiveSelectionMode == SynSelectionMode::smColumn) ||
+ ((edit->mActiveSelectionMode == SynSelectionMode::smNormal) && (cRow == vSelStart.Row)) ) {
+ if (vSelStart.Column > LastCol) {
+ nLineSelStart = 0;
+ nLineSelEnd = 0;
+ } else if (vSelStart.Column > FirstCol) {
+ nLineSelStart = vSelStart.Column;
+ bComplexLine = true;
+ }
}
- if sToken = '[' then begin
- GetBraceColorAttr(fHighlighter.GetBracketLevel,attr);
- end else if sToken = ']' then begin
- GetBraceColorAttr(fHighlighter.GetBracketLevel+1,attr);
- end else if sToken = '(' then begin
- GetBraceColorAttr(fHighlighter.GetParenthesisLevel,attr);
- end else if sToken = ')' then begin
- GetBraceColorAttr(fHighlighter.GetParenthesisLevel+1,attr);
- end else if sToken = '{' then begin
- GetBraceColorAttr(fHighlighter.GetBraceLevel,attr);
- end else if sToken = '}' then begin
- GetBraceColorAttr(fHighlighter.GetBraceLevel+1,attr);
- end;
- AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
- nTokenLen, cRow,attr);
- end;
- // Let the highlighter scan the next token.
- fHighlighter.Next;
- end;
- // Don't assume HL.GetTokenPos is valid after HL.GetEOL = True.
- Inc(nTokenPos, Length(sToken));
- if fHighlighter.GetEol and (nTokenPos < vLastChar) then begin
- // Draw text that couldn't be parsed by the highlighter, if any.
- if nTokenPos < Length(sLine) then begin
- if nTokenPos + 1 < vFirstChar then
- nTokenPos := vFirstChar - 1;
- nTokenLen := Min(Length(sLine), vLastChar) - (nTokenPos + 1);
- if nTokenLen > 0 then begin
- sToken := Copy(sLine, nTokenPos + 1, nTokenLen);
- AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
- nTokenLen, cRow, nil);
- end;
- end;
- // Draw LineBreak glyph.
- if (eoShowSpecialChars in fOptions) and (not bLineSelected)
- and (not bSpecialLine) and (Length(sLine) < vLastChar) then begin
- AddHighlightToken(SynLineBreakGlyph,
- Length(sLine) - (vFirstChar - FirstCol),
- Length(SynLineBreakGlyph),cRow, fHighLighter.WhitespaceAttribute);
- end;
- end;
+ if ( (edit->mActiveSelectionMode == SynSelectionMode::smColumn) ||
+ ((edit->mActiveSelectionMode == SynSelectionMode::smNormal) && (cRow == vSelEnd.Row)) ) {
+ if (vSelEnd.Column < FirstCol) {
+ nLineSelStart = 0;
+ nLineSelEnd = 0;
+ } else if (vSelEnd.Column < LastCol) {
+ nLineSelEnd = vSelEnd.Column;
+ bComplexLine = true;
+ }
+ }
+ } //endif bAnySelection
- // Paint folding
- foldRange := FoldStartAtLine(vLine);
- if assigned(foldRange) and foldRange.Collapsed then begin
- sFold := ' ... }';
- nFold := Length(sFold);
- Attr := fHighlighter.SymbolAttribute;
- GetBraceColorAttr(fHighlighter.GetBraceLevel,attr);
- AddHighlightToken(sFold,Length(sLine)+1 - (vFirstChar - FirstCol)
- , nFold, cRow, attr);
- // Compute some helper variables.
- //nC1 := Max(FirstCol, Length(sLine)+1);
- //nC2 := Min(LastCol, Length(sLine) +1 + nFold + 1);
- //SetDrawingColors(FALSE);
- //PaintToken(sFold,nFold, Length(sLine)+1,nC1, nC2);
- end;
+ // Update the rcLine rect to this line.
+ rcLine.setTop(rcLine.bottom());
+ rcLine.setBottom(rcLine.bottom()+edit->mTextHeight);
- // Draw anything that's left in the TokenAccu record. Fill to the end
- // of the invalid area with the correct colors.
- PaintHighlightToken(TRUE);
+ bLineSelected = (!bComplexLine) && (nLineSelStart > 0);
+ rcToken = rcLine;
+ if (!edit->mHighlighter || !edit->mHighlighter->enabled()) {
+ sToken = sLine;
+ nTokenLen = edit->mLines->lineColumns(vLine-1);
+ if (edit->mShowSpecChar && (!bLineSelected) && (!bSpecialLine) && (nTokenLen < vLastChar)) {
+ sToken = sToken + SynLineBreakGlyph;
+ nTokenLen = sToken + edit->charColumns(SynLineBreakGlyph);
+ }
+ if (bComplexLine) {
+ setDrawingColors(false);
+ rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(FirstCol)));
+ rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelStart)));
+ PaintToken(sToken, nTokenLen, 0, FirstCol, nLineSelStart,false);
+ rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelEnd)));
+ rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(LastCol)));
+ PaintToken(sToken, nTokenLen, 0, nLineSelEnd, LastCol,true);
+ setDrawingColors(false);
+ rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelStart)));
+ rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelEnd)));
+ PaintToken(sToken, nTokenLen, 0, nLineSelStart, nLineSelEnd - 1,false);
+ } else {
+ setDrawingColors(bLineSelected);
+ PaintToken(sToken, nTokenLen, 0, FirstCol, LastCol,bLineSelected);
+ }
+ } else {
+ // Initialize highlighter with line text and range info. It is
+ // necessary because we probably did not scan to the end of the last
+ // line - the internal highlighter range might be wrong.
+ if (vLine == 1) {
+ edit->mHighlighter->resetState();
+ } else {
+ edit->mHighlighter->setState(
+ edit->mLines->ranges(vLine-2),
+ edit->mLines->braceLevels(vLine-2),
+ edit->mLines->bracketLevels(vLine-2),
+ edit->mLines->parenthesisLevels(vLine-2)
+ );
+ edit->mHighlighter->setLine(sLine, vLine - 1);
+ }
+ // Try to concatenate as many tokens as possible to minimize the count
+ // of ExtTextOut calls necessary. This depends on the selection state
+ // or the line having special colors. For spaces the foreground color
+ // is ignored as well.
+ TokenAccu.Columns = 0;
+ nTokenPos = 0;
+ // Test first whether anything of this token is visible.
+ while (edit->mHighlighter->eol()) {
+ sToken = edit->mHighlighter->getToken();
+ // Work-around buggy highlighters which return empty tokens.
+ if (sToken.isEmpty()) {
+ edit->mHighlighter->next();
+ if (edit->mHighlighter->eol())
+ break;
+ sToken = edit->mHighlighter->getToken();
+ // Maybe should also test whether GetTokenPos changed...
+ if (sToken.isEmpty())
+ throw BaseError(SynEdit::tr("The highlighter seems to be in an infinite loop"));
+ }
+ nTokenPos = edit->charToColumn(vLine,edit->mHighlighter->getTokenPos());
+ nTokenLen = edit->stringColumns(sToken);
+ if (nTokenPos + nTokenLen >= vFirstChar) {
+ if (nTokenPos + nTokenLen >= vLastChar) {
+ if (nTokenPos >= vLastChar)
+ break; //*** BREAK ***
+ nTokenLen = vLastChar - nTokenPos - 1;
+ }
+ // It's at least partially visible. Get the token attributes now.
+ attr = edit->mHighlighter->getTokenAttribute();
+ if (sToken == "[") {
+ GetBraceColorAttr(edit->mHighlighter->getBracketLevel(),attr);
+ } else if (sToken == "]") {
+ GetBraceColorAttr(edit->mHighlighter->getBracketLevel()+1,attr);
+ } else if (sToken == "(") {
+ GetBraceColorAttr(edit->mHighlighter->getParenthesisLevel(),attr);
+ } else if (sToken == ")") {
+ GetBraceColorAttr(edit->mHighlighter->getParenthesisLevel()+1,attr);
+ } else if (sToken == "{") {
+ GetBraceColorAttr(edit->mHighlighter->getBraceLevel(),attr);
+ } else if (sToken == "}") {
+ GetBraceColorAttr(edit->mHighlighter->getBraceLevel()+1,attr);
+ }
+ AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
+ nTokenLen, vLine,attr);
+ }
+ // Let the highlighter scan the next token.
+ edit->mHighlighter->next();
+ }
+ // Don't assume HL.GetTokenPos is valid after HL.GetEOL == True.
+ nTokenPos += edit->stringColumns(sToken);
+ if (edit->mHighlighter->eol() && (nTokenPos < vLastChar)) {
+ int lineColumns = edit->mLines->lineColumns(vLine-1);
+ // Draw text that couldn't be parsed by the highlighter, if any.
+ if (nTokenPos < lineColumns) {
+ if (nTokenPos + 1 < vFirstChar)
+ nTokenPos = vFirstChar - 1;
+ nTokenLen = std::min(lineColumns, vLastChar) - (nTokenPos + 1);
+ if (nTokenLen > 0) {
+ sToken = edit->subStringByColumns(sLine,nTokenPos+1,nTokenLen);
+ AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
+ edit->stringColumns(sToken), vLine, PSynHighlighterAttribute());
+ }
+ }
+ // Draw LineBreak glyph.
+ if (edit->mShowSpecChar && (!bLineSelected) &&
+ (!bSpecialLine) && (edit->mLines->lineColumns(vLine-1) < vLastChar)) {
+ AddHighlightToken(SynLineBreakGlyph,
+ edit->mLines->lineColumns(vLine-1) - (vFirstChar - FirstCol),
+ edit->charColumns(SynLineBreakGlyph),vLine, edit->mHighlighter->whitespaceAttribute());
+ }
+ }
- //Paint editingAreaBorders
- PaintEditAreas(areaList,colBorder,areaType);
+ // Paint folding
+ foldRange = edit->foldStartAtLine(vLine);
+ if ((foldRange) && foldRange->collapsed) {
+ sFold = " ... } ";
+ nFold = edit->stringColumns(sFold);
+ attr = edit->mHighlighter->symbolAttribute();
+ GetBraceColorAttr(edit->mHighlighter->getBraceLevel(),attr);
+ AddHighlightToken(sFold,edit->mLines->lineColumns(vLine-1)+1 - (vFirstChar - FirstCol)
+ , nFold, vLine, attr);
+ }
- end;
+ // Draw anything that's left in the TokenAccu record. Fill to the end
+ // of the invalid area with the correct colors.
+ PaintHighlightToken(true);
- // Now paint the right edge if necessary. We do it line by line to reduce
- // the flicker. Should not cost very much anyway, compared to the many
- // calls to ExtTextOut.
- if bDoRightEdge then begin
- Canvas.MoveTo(nRightEdge, rcLine.Top);
- Canvas.LineTo(nRightEdge, rcLine.Bottom + 1);
- end;
- bCurrentLine := False;
- end; //endfor cRow
+ //Paint editingAreaBorders
+ PaintEditAreas(areaList);
+ }
+
+ // Now paint the right edge if necessary. We do it line by line to reduce
+ // the flicker. Should not cost very much anyway, compared to the many
+ // calls to ExtTextOut.
+ if (bDoRightEdge) {
+ painter->paintEngine(nRightEdge, rcLine.top(),nRightEdge,rcLine.bottom()+1);
+ }
+ bCurrentLine = false;
+ }
}
diff --git a/RedPandaIDE/qsynedit/TextPainter.h b/RedPandaIDE/qsynedit/TextPainter.h
index 82951bc6..c9fa76c7 100644
--- a/RedPandaIDE/qsynedit/TextPainter.h
+++ b/RedPandaIDE/qsynedit/TextPainter.h
@@ -6,6 +6,7 @@
#include
#include "Types.h"
#include "highlighter/base.h"
+#include "../utils.h"
class SynEdit;
class SynEditTextPainter
@@ -35,7 +36,7 @@ public:
int cLine, PSynHighlighterAttribute p_Attri);
void PaintFoldAttributes();
- void GetBraceColorAttr(int level, const PSynHighlighterAttribute& attr);
+ void GetBraceColorAttr(int level, PSynHighlighterAttribute &attr);
void PaintLines();
private:
SynEdit* edit;
diff --git a/RedPandaIDE/qsynedit/highlighter/base.cpp b/RedPandaIDE/qsynedit/highlighter/base.cpp
index a09200c9..776070e7 100644
--- a/RedPandaIDE/qsynedit/highlighter/base.cpp
+++ b/RedPandaIDE/qsynedit/highlighter/base.cpp
@@ -161,6 +161,19 @@ PSynHighlighterAttribute SynHighlighter::getAttribute(const QString &name) const
return PSynHighlighterAttribute();
}
+bool SynHighlighter::enabled() const
+{
+ return mEnabled;
+}
+
+void SynHighlighter::setEnabled(bool value)
+{
+ if (value != mEnabled) {
+ mEnabled = value;
+ setAttributesChanged();
+ }
+}
+
void SynHighlighterAttribute::setChanged()
{
emit changed();
diff --git a/RedPandaIDE/qsynedit/highlighter/base.h b/RedPandaIDE/qsynedit/highlighter/base.h
index a799a0d5..e86749a6 100644
--- a/RedPandaIDE/qsynedit/highlighter/base.h
+++ b/RedPandaIDE/qsynedit/highlighter/base.h
@@ -112,6 +112,9 @@ public:
virtual QString languageName();
static bool isSpaceChar(const QChar& ch);
+ bool enabled() const;
+ void setEnabled(bool value);
+
signals:
void attributesChanged();
diff --git a/Red_Panda_CPP.pro b/Red_Panda_CPP.pro
index ce9748e1..b737f4d8 100644
--- a/Red_Panda_CPP.pro
+++ b/Red_Panda_CPP.pro
@@ -1,5 +1,5 @@
TEMPLATE = subdirs
SUBDIRS += \
- ../QScintilla/src/qscintilla.pro \
+# ../QScintilla/src/qscintilla.pro \
RedPandaIDE