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