* work save

This commit is contained in:
royqh1979@gmail.com 2021-05-21 23:33:53 +08:00
parent c7a7f69285
commit 101302255b
11 changed files with 521 additions and 83 deletions

View File

@ -3,4 +3,7 @@ const QSet<QChar> SynWordBreakChars{'.', ',', ';', ':',
'"', '\'', '!', '?', '[', ']', '(', ')', '{', '}', '^', '-', '=', '+',
'-', '*', '/', '\\', '|'};
const QChar SynTabChar('\t');
const QChar SynSpaceGlyph(' ');
const QChar SynTabGlyph(0x2192);
const QChar SynSpaceGlyph('.');
const QChar SynLineBreakGlyph(0x2193);
const QChar SynSoftBreakGlyph(0x2193);

View File

@ -6,6 +6,10 @@
extern const QSet<QChar> SynWordBreakChars;
extern const QChar SynTabChar;
extern const QChar SynSpaceGlyph;
extern const QChar SynTabGlyph;
extern const QChar SynLineBreakGlyph;
extern const QChar SynSoftBreakGlyph;
#define MAX_SCROLL 65535

View File

@ -56,6 +56,19 @@ void SynGutter::setChanged()
emit changed();
}
QColor SynGutter::textColor() const
{
return mTextColor;
}
void SynGutter::setTextColor(const QColor &value)
{
if (mTextColor!=value) {
mTextColor = value;
setChanged();
}
}
int SynGutter::width() const
{
return mWidth;

View File

@ -76,6 +76,9 @@ public:
QString formatLineNumber(int line);
int realGutterWidth(int charWidth);
QColor textColor() const;
void setTextColor(const QColor &value);
signals:
void changed();
private:
@ -83,6 +86,7 @@ private:
private:
bool mAutoSize;
QColor mBorderColor;
QColor mTextColor;
QColor mColor;
int mDigitCount;
QFont mFont;

View File

@ -254,7 +254,7 @@ void SynEdit::invalidateGutterLines(int FirstLine, int LastLine)
if (!isVisible())
return;
if (FirstLine == -1 && LastLine == -1) {
rcInval = QRect(clientLeft(), clientTop(), mGutterWidth, clientHeight());
rcInval = QRect(0, 0, mGutterWidth, clientHeight());
if (mStateFlags.testFlag(SynStateFlag::sfLinesChanging))
mInvalidateRect = mInvalidateRect.united(rcInval);
else
@ -274,7 +274,7 @@ void SynEdit::invalidateGutterLines(int FirstLine, int LastLine)
LastLine = std::min(LastLine, mTopLine + mLinesInWindow);
// any line visible?
if (LastLine >= FirstLine) {
rcInval = {clientLeft(), clientTop()+mTextHeight * (FirstLine - mTopLine),
rcInval = {0, mTextHeight * (FirstLine - mTopLine),
mGutterWidth, mTextHeight * (LastLine - mTopLine + 1)};
if (mStateFlags.testFlag(SynStateFlag::sfLinesChanging)) {
mInvalidateRect = mInvalidateRect.united(rcInval);
@ -379,22 +379,38 @@ int SynEdit::charToColumn(int aLine, int aChar)
throw BaseError(SynEdit::tr("Line %1 is out of range").arg(aLine));
}
int SynEdit::stringColumns(const QString &line)
int SynEdit::stringColumns(const QString &line, int colsBefore)
{
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;
int columns = colsBefore;
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-colsBefore;
}
int SynEdit::getLineIndent(const QString &line)
{
int indents = 0;
for (QChar ch:line) {
switch(ch.digitValue()) {
case '\t':
indents+=mTabWidth;
break;
case ' ':
indents+=1;
break;
default:
return indents;
}
}
return columns;
return indents;
}
int SynEdit::rowToLine(int aRow)
@ -576,6 +592,8 @@ void SynEdit::clearUndo()
int SynEdit::charColumns(QChar ch)
{
if (ch == ' ')
return 1;
return std::ceil(fontMetrics().horizontalAdvance(ch) * dpiFactor() / mCharWidth);
}
@ -751,7 +769,7 @@ int SynEdit::clientLeft()
QRect SynEdit::clientRect()
{
return QRect(clientLeft(),clientTop(), clientWidth(), clientHeight());
return QRect(0,0, clientWidth(), clientHeight());
}
void SynEdit::synFontChanged()
@ -1274,6 +1292,83 @@ void SynEdit::initializeCaret()
//todo:
}
PSynEditFoldRange SynEdit::foldStartAtLine(int Line)
{
for (int i = 0; i<mAllFoldRanges.count();i++) {
PSynEditFoldRange range = mAllFoldRanges[i];
if (range->fromLine == Line ){
return range;
} else if (range->fromLine>Line)
break; // sorted by line. don't bother scanning further
}
}
QString SynEdit::substringByColumns(const QString &s, int startColumn, int &colLen)
{
int len = s.length();
int columns = 0;
int i = 0;
int oldColumns;
while (columns < startColumn) {
oldColumns = columns;
if (i < len && s[i] == '\t')
columns += mTabWidth - (columns % mTabWidth);
else
columns += charColumns(s[i]);
i++;
}
QString result;
if (i>=len) {
colLen = 0;
return result;
}
if (colLen>result.capacity()) {
result.resize(colLen);
}
int j=0;
if (i>0) {
result[0]=s[i-1];
j++;
}
while (i<len && columns<startColumn+colLen) {
result[j]=s[i];
if (i < len && s[i] == '\t')
columns += mTabWidth - (columns % mTabWidth);
else
columns += charColumns(s[i]);
i++;
j++;
}
result.resize(j);
colLen = columns-oldColumns;
return result;
}
PSynEditFoldRange SynEdit::foldAroundLine(int Line)
{
return foldAroundLineEx(Line,false,false,false);
}
PSynEditFoldRange SynEdit::foldAroundLineEx(int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine)
{
}
PSynEditFoldRange SynEdit::CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck, int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine)
{
for (int i = 0; i< FoldRangeToCheck->count(); i++) {
PSynEditFoldRange range = (*FoldRangeToCheck)[i];
if (((range->fromLine < Line) || ((range->fromLine <= Line) && AcceptFromLine)) &&
((range->toLine > Line) || ((range->toLine >= Line) && AcceptToLine))) {
if (range->collapsed == WantCollapsed) {
return range;
}
}
}
return PSynEditFoldRange();
}
void SynEdit::sizeOrFontChanged(bool bFont)
{
if (mCharWidth != 0) {
@ -1307,6 +1402,16 @@ int SynEdit::tabWidth() const
return mTabWidth;
}
bool SynEdit::onSpecialLineColors(int, QColor &, QColor &)
{
}
void SynEdit::onEditingAreas(int, SynEditingAreaList &)
{
}
void SynEdit::paintEvent(QPaintEvent *event)
{
if (mPainterLock>0)
@ -1320,10 +1425,10 @@ void SynEdit::paintEvent(QPaintEvent *event)
rcClip = event->rect();
// columns
nC1 = mLeftChar;
if (rcClip.left() > mGutterWidth + 2 + clientLeft())
nC1 += (rcClip.left() - mGutterWidth - 2 - clientLeft()) % mCharWidth;
if (rcClip.left() > mGutterWidth + 2 )
nC1 += (rcClip.left() - mGutterWidth - 2 ) % mCharWidth;
nC2 = mLeftChar +
(rcClip.right() - mGutterWidth - 2 - clientLeft() + mCharWidth - 1) % mCharWidth;
(rcClip.right() - mGutterWidth - 2 + mCharWidth - 1) % mCharWidth;
// lines
nL1 = MinMax(mTopLine + rcClip.top() % mTextHeight, mTopLine, displayLineCount());
nL2 = MinMax(mTopLine + (rcClip.bottom() + mTextHeight - 1) % mTextHeight, 1, displayLineCount());
@ -1336,23 +1441,23 @@ void SynEdit::paintEvent(QPaintEvent *event)
});
// First paint paint the text area if it was (partly) invalidated.
if (rcClip.right() > mGutterWidth + clientLeft()) {
if (rcClip.right() > mGutterWidth ) {
rcDraw = rcClip;
rcDraw.setLeft( std::max(rcDraw.left(), mGutterWidth + clientLeft()));
rcDraw.setLeft( std::max(rcDraw.left(), mGutterWidth));
paintTextLines(rcDraw, nL1, nL2, nC1, nC2);
}
// Then the gutter area if it was (partly) invalidated.
if (rcClip.left() < clientLeft() + mGutterWidth) {
if (rcClip.left() < mGutterWidth) {
rcDraw = rcClip;
rcDraw.setRight(clientLeft() + mGutterWidth);
rcDraw.setRight(mGutterWidth);
paintGutter(rcDraw, nL1, nL2);
}
//PluginsAfterPaint(Canvas, rcClip, nL1, nL2);
// If there is a custom paint handler call it.
doOnPaint();
doOnPaintTransient(SynTransientType:: ttAfter);
doOnPaintTransient(SynTransientType::ttAfter);
}
int SynEdit::maxScrollWidth() const

View File

@ -125,12 +125,12 @@ using SynPreparePaintHighlightTokenProc = std::function<void(int row,
SynFontStyles& style, QColor& foreground, QColor& background)>;
using SynReplaceTextProc = std::function<void(const QString& ASearch, const QString& AReplace,
int Line, int Column, int wordLen, SynReplaceAction& action)>;
using SynSpecialLineColorsProc = std::function<void(int Line,
bool& Special, QColor& foreground, QColor& backgroundColor)>;
using SynEditingAreasProc = std::function<void(int Line, SynEditingAreaList& areaList,
QColor& borderColor,SynEditingAreaType& areaType)>;
using SynGutterGetTextProc = std::function<void(int aLine, QString& aText)>;
using SynTGutterPaintProc = std::function<void(int aLine, int X, int Y)>;
//using SynSpecialLineColorsProc = std::function<void(int Line,
// bool& Special, QColor& foreground, QColor& backgroundColor)>;
//using SynEditingAreasProc = std::function<void(int Line, SynEditingAreaList& areaList,
// QColor& borderColor,SynEditingAreaType& areaType)>;
//using SynGutterGetTextProc = std::function<void(int aLine, QString& aText)>;
//using SynTGutterPaintProc = std::function<void(int aLine, int X, int Y)>;
class SynEdit;
using PSynEdit = std::shared_ptr<SynEdit>;
@ -163,7 +163,8 @@ public:
DisplayCoord bufferToDisplayPos(const BufferCoord& p);
BufferCoord displayToBufferPos(const DisplayCoord& p);
int charToColumn(int aLine, int aChar);
int stringColumns(const QString& line);
int stringColumns(const QString& line, int colsBefore);
int getLineIndent(const QString& line);
int rowToLine(int aRow);
int lineToRow(int aLine);
int foldRowToLine(int Row);
@ -241,6 +242,15 @@ signals:
void fontChanged();
void tabSizeChanged();
protected:
virtual bool onSpecialLineColors(int Line,
QColor& foreground, QColor& backgroundColor) ;
virtual void onEditingAreas(int Line, SynEditingAreaList& areaList);
virtual void onGutterGetText(int aLine, QString& aText);
virtual void onGutterPaint(int aLine, int X, int Y);
private:
void clearAreaList(SynEditingAreaList areaList);
void computeCaret(int X, int Y);
@ -287,6 +297,11 @@ private:
const QString& Value, bool AddToUndoList);
void doOnPaintTransientEx(SynTransientType TransientType, bool Lock);
void initializeCaret();
PSynEditFoldRange foldStartAtLine(int Line);
QString substringByColumns(const QString& s, int startColumn, int& colLen);
PSynEditFoldRange foldAroundLine(int Line);
PSynEditFoldRange foldAroundLineEx(int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine);
PSynEditFoldRange CheckFoldRange(PSynEditFoldRanges FoldRangeToCheck,int Line, bool WantCollapsed, bool AcceptFromLine, bool AcceptToLine);
private slots:
void bookMarkOptionsChanged();
@ -400,10 +415,10 @@ private:
SynProcessCommandProc mOnProcessingUserCommand;
SynReplaceTextProc mOnReplaceText;
SynSpecialLineColorsProc mOnSpecialLineColors;
SynEditingAreasProc mOnEditingAreas;
SynGutterGetTextProc mOnGutterGetText;
SynTGutterPaintProc mOnGutterPaint;
// SynSpecialLineColorsProc mOnSpecialLineColors;
// SynEditingAreasProc mOnEditingAreas;
// SynGutterGetTextProc mOnGutterGetText;
// SynTGutterPaintProc mOnGutterPaint;
int mGutterWidth;
//caret blink related
@ -418,6 +433,4 @@ protected:
friend class SynEditTextPainter;
};
class
#endif // SYNEDIT_H

View File

@ -379,7 +379,7 @@ int SynEditStringList::calculateLineColumns(int Index)
{
PSynEditStringRec line = mList[Index];
line->fColumns = mEdit->stringColumns(line->fString);
line->fColumns = mEdit->stringColumns(line->fString,0);
return line->fColumns;
}

View File

@ -3,9 +3,276 @@
#include "Constants.h"
#include <cmath>
SynEditTextPainter::SynEditTextPainter(SynEdit *edit)
SynEditTextPainter::SynEditTextPainter(SynEdit *edit, int FirstRow, int LastRow, int FirstCol, int LastCol)
{
this->edit = edit;
this->aFirstRow = FirstRow;
this->aLastRow = LastRow;
this->FirstCol = FirstCol;
this->LastCol = LastCol;
}
void SynEditTextPainter::paintTextLines(const QRect& clip)
{
AClip = clip;
vFirstLine = edit->rowToLine(aFirstRow);
vLastLine = edit->rowToLine(aLastRow);
bCurrentLine = false;
// If the right edge is visible and in the invalid area, prepare to paint it.
// Do this first to realize the pen when getting the dc variable.
QString SynTabGlyphString = SynTabGlyph;
bDoRightEdge = false;
if (edit->mRightEdge > 0) { // column value
nRightEdge = edit->mTextOffset + edit->mRightEdge * edit->mCharWidth; // pixel value
if (nRightEdge >= AClip.left() &&nRightEdge <= AClip.right()) {
bDoRightEdge = true;
QPen pen(edit->mRightEdgeColor,1);
painter->setPen(pen);
}
}
// Paint the visible text lines. To make this easier, compute first the
// necessary information about the selected area: is there any visible
// selected area, and what are its lines / columns?
if (vLastLine >= vFirstLine) {
ComputeSelectionInfo();
PaintLines();
}
// If anything of the two pixel space before the text area is visible, then
// fill it with the component background color.
if (AClip.left() < edit->clientLeft()+ edit->mGutterWidth + 2) {
rcToken = AClip;
rcToken.setLeft( std::max(AClip.left(), edit->mGutterWidth));
rcToken.setRight(edit->mGutterWidth + 2);
// Paint whole left edge of the text with same color.
// (value of WhiteAttribute can vary in e.g. MultiSyn)
painter->setPen(Qt::NoPen);
painter->setBrush(colEditorBG());
painter->drawRect(rcToken);
// Adjust the invalid area to not include this area.
AClip.setLeft(rcToken.right());
}
// If there is anything visible below the last line, then fill this as well.
rcToken = AClip;
rcToken.setTop((aLastRow - edit->mTopLine + 1) * edit->mTextHeight);
if (rcToken.top() < rcToken.bottom()) {
painter->setPen(Qt::NoPen);
painter->setBrush(colEditorBG());
painter->drawRect(rcToken);
// Draw the right edge if necessary.
if (bDoRightEdge) {
QPen pen(edit->mRightEdgeColor,1);
painter->setPen(pen);
painter->drawLine(nRightEdge, rcToken.top(),nRightEdge, rcToken.bottom() + 1);
}
}
// This messes with pen colors, so draw after right margin has been drawn
PaintFoldAttributes();
}
void SynEditTextPainter::paintGutter(const QRect& clip)
{
int cRow;
int cMark;
QRect rcLine, rcFold;
QList<int> aGutterOffs;
bool bHasOtherMarks;
QString s;
int vFirstLine;
int vLastLine;
int vLine;
int vMarkRow;
int vGutterRow;
int vLineTop;
QSize TextSize;
int x;
PSynEditFoldRange FoldRange;
AClip = clip;
//todo: Does the following comment still apply?
// Changed to use fTextDrawer.BeginDrawing and fTextDrawer.EndDrawing only
// when absolutely necessary. Note: Never change brush / pen / font of the
// canvas inside of this block (only through methods of fTextDrawer)!
// If we have to draw the line numbers then we don't want to erase
// the background first. Do it line by line with TextRect instead
// and fill only the area after the last visible line.
painter->setBrush(edit->mGutter.color());
painter->setPen(Qt::NoPen);
rcLine=AClip;
painter->drawRect(AClip);
if (edit->mGutter.showLineNumbers()) {
if (edit->mGutter.useFontStyle()) {
painter->setFont(edit->mGutter.font());
painter->setPen(edit->mGutter.textColor());
} else {
painter->setPen(edit->palette().color(QPalette::Text));
}
painter->setBrush(edit->mGutter.color());
// prepare the rect initially
rcLine = AClip;
rcLine.setRight( std::max(rcLine.right(), edit->mGutterWidth - 2));
rcLine.setBottom(rcLine.top());
painter->drawRect(AClip);
// draw each line if it is not hidden by a fold
for (int cRow = aFirstRow; cRow <= aLastRow; cRow++) {
vLine = edit->rowToLine(cRow);
if ((vLine > edit->mLines->count()) && (edit->mLines->count() > 0 ))
break;
vLineTop = (cRow - edit->mTopLine) * edit->mTextHeight;
// next line rect
rcLine.setTop(vLineTop);
rcLine.setBottom(rcLine.top() + edit->mTextHeight);
s = edit->mGutter.formatLineNumber(vLine);
if (edit->mOnGutterGetText) {
edit->mOnGutterGetText(vLine,s);
}
QRectF textRect;
textRect = painter->boundingRect(textRect, Qt::AlignLeft,s);
painter->drawText(
(edit->mGutterWidth - edit->mGutter.rightOffset() - 2) - textRect.width(),
rcLine.top() + ((edit->mTextHeight - int(textRect.height())) % 2),
s
);
}
}
// Draw the folding lines and squares
if (edit->mUseCodeFolding) {
for (cRow = aFirstRow; cRow<=aLastRow; cRow++) {
vLine = edit->rowToLine(cRow);
if ((vLine > edit->mLines->count()) && (edit->mLines->count() != 0))
break;
// Form a rectangle for the square the user can click on
//rcFold.Left := Gutter.RealGutterWidth(CharWidth) - Gutter.RightOffset;
rcFold.setLeft(edit->mGutterWidth - edit->mGutter.rightOffset());
rcFold.setRight(rcFold.left() + edit->mGutter.rightOffset() - 4);
rcFold.setTop((cRow - edit->mTopLine) * edit->mTextHeight);
rcFold.setBottom(rcFold.top() + edit->mTextHeight);
painter->setPen(edit->mCodeFolding.folderBarLinesColor);
// Need to paint a line?
if (edit->foldAroundLine(vLine)) {
x = rcFold.left() + (rcFold.width() % 2);
painter->drawLine(x,rcFold.top(), x, rcFold.bottom());
}
// Need to paint a line end?
if (edit->foldEndAtLine(vLine)) {
x = rcFold.left() + (rcFold.width() % 2);
painter->drawLine(x,rcFold.top(), x, rcFold.top() + rcFold.height() % 2);
painter->drawLine(x,
rcFold.top() + rcFold.height() % 2,
rcFold.right() - 2 ,
rcFold.top() + rcFold.height() % 2);
}
// Any fold ranges beginning on this line?
FoldRange = edit->foldStartAtLine(vLine);
if (FoldRange) {
// Draw the bottom part of a line
if (!FoldRange->collapsed) {
x = rcFold.left() + (rcFold.width() % 2);
painter->drawLine(x, rcFold.top() + rcFold.height() % 2,
x, rcFold.bottom());
}
// make a square rect
inflateRect(rcFold,-2, 0);
rcFold.setTop(
rcFold.top() + ((edit->mTextHeight - rcFold.width()) % 2));
rcFold.setBottom(rcFold.top() + rcFold.width());
// Paint the square the user can click on
painter->setBrush(edit->mGutter.color());
painter->setPen(edit->mCodeFolding.folderBarLinesColor);
painter->drawRect(rcFold);
// Paint minus sign
painter->drawLine(
rcFold.left() + 2, rcFold.top() + (rcFold.height() % 2 ),
rcFold.right() - 2, rcFold.top() + (rcFold.height() % 2 ));
// Paint vertical line of plus sign
if (FoldRange->collapsed) {
x = rcFold.left() + (rcFold.width() % 2);
painter->drawLine(x, rcFold.top() + 2,
x, rcFold.bottom() + 2);
}
}
}
}
// // the gutter separator if visible
// if (edit->mGutter.borderStyle <> gbsNone) and (AClip.Right >= fGutterWidth - 2) then
// with Canvas do begin
// Pen.Color := fGutter.BorderColor;
// Pen.Width := 1;
// with AClip do begin
// if fGutter.BorderStyle = gbsMiddle then begin
// MoveTo(fGutterWidth - 2, Top);
// LineTo(fGutterWidth - 2, Bottom);
// Pen.Color := fGutter.Color;
// end;
// MoveTo(fGutterWidth - 1, Top);
// LineTo(fGutterWidth - 1, Bottom);
// end;
// end;
// // now the gutter marks
// if BookMarkOptions.GlyphsVisible and (Marks.Count > 0) and (aLastRow >= aFirstRow) then begin
// aGutterOffs := AllocMem((aLastRow - aFirstRow + 1) * SizeOf(integer));
// vFirstLine := RowToLine(aFirstRow);
// vLastLine := RowToLine(aLastRow);
// try
// // Instead of making a two pass loop we look while drawing the bookmarks
// // whether there is any other mark to be drawn
// bHasOtherMarks := FALSE;
// for cMark := 0 to Marks.Count - 1 do
// with Marks[cMark] do
// if Visible and (Line >= vFirstLine) and (Line <= vLastLine) then begin
// if IsBookmark <> BookMarkOptions.DrawBookmarksFirst then
// bHasOtherMarks := TRUE
// else begin
// vMarkRow := LineToRow(Line);
// if vMarkRow >= aFirstRow then
// DrawMark(Marks[cMark], aGutterOffs[vMarkRow - aFirstRow], vMarkRow);
// end
// end;
// if bHasOtherMarks then
// for cMark := 0 to Marks.Count - 1 do
// with Marks[cMark] do begin
// if Visible and (IsBookmark <> BookMarkOptions.DrawBookmarksFirst)
// and (Line >= vFirstLine) and (Line <= vLastLine) then begin
// vMarkRow := LineToRow(Line);
// if vMarkRow >= aFirstRow then
// DrawMark(Marks[cMark], aGutterOffs[vMarkRow - aFirstRow], vMarkRow);
// end;
// end;
// if Assigned(OnGutterPaint) then
// for cRow := aFirstRow to aLastRow do begin
// OnGutterPaint(Self, cRow, aGutterOffs[cRow - aFirstRow],
// (vGutterRow - TopLine) * LineHeight);
// end;
// finally
// FreeMem(aGutterOffs);
// end;
// end;
for (cRow = aFirstRow; cRow <=aLastRow; cRow++) {
vLine = edit->rowToLine(cRow);
edit->onGutterPaint(vLine, 0, (cRow - edit->mTopLine) * edit->mTextHeight);
}
}
QColor SynEditTextPainter::colEditorBG()
@ -127,7 +394,7 @@ void SynEditTextPainter::PaintToken(const QString &Token, int TokenCols, int Col
}
}
void SynEditTextPainter::PaintEditAreas(PSynEditingAreaList areaList)
void SynEditTextPainter::PaintEditAreas(const SynEditingAreaList &areaList)
{
QRect rc;
int x1,x2;
@ -136,7 +403,7 @@ void SynEditTextPainter::PaintEditAreas(PSynEditingAreaList areaList)
rc=rcLine;
rc.setBottom(rc.bottom()-1);
setDrawingColors(false);
for (PSynEditingArea p:*areaList) {
for (PSynEditingArea p:areaList) {
if (p->beginX > LastCol)
continue;
if (p->endX < FirstCol)
@ -393,7 +660,7 @@ void SynEditTextPainter::PaintFoldAttributes()
LastNonBlank = vLine - 1;
while (LastNonBlank + 1 < edit->mLines->count() && edit->mLines->getString(LastNonBlank).trimmed().isEmpty())
LastNonBlank++;
LineIndent = edit->GetLineIndent(edit->mLines->getString(LastNonBlank));
LineIndent = edit->getLineIndent(edit->mLines->getString(LastNonBlank));
// Step horizontal coord
TabSteps = edit->mTabWidth;
while (TabSteps < LineIndent) {
@ -408,7 +675,7 @@ void SynEditTextPainter::PaintFoldAttributes()
}
if (!edit->mUseCodeFolding)
exit;
return;
// Paint collapsed lines using changed pen
if (edit->mCodeFolding.showCollapsedLine) {
@ -450,11 +717,11 @@ void SynEditTextPainter::PaintLines()
int vLine;
QString sLine; // the current line
QString sToken; // highlighter token info
int nTokenPos, nTokenLen;
int nTokenStartColumn, nTokenColumnLen;
PSynHighlighterAttribute attr;
int vFirstChar;
int vLastChar;
PSynEditingAreaList areaList;
SynEditingAreaList areaList;
QColor colBorder;
PSynEditFoldRange foldRange;
int nC1,nC2,nFold;
@ -480,7 +747,7 @@ void SynEditTextPainter::PaintLines()
// use special values for them.
colFG = edit->palette().color(QPalette::Text);
colBG = colEditorBG();
bSpecialLine = edit->DoOnSpecialLineColors(vLine, colFG, colBG);
bSpecialLine = edit->onSpecialLineColors(vLine, colFG, colBG);
if (bSpecialLine) {
// The selection colors are just swapped, like seen in Delphi.
colSelFG = colBG;
@ -489,7 +756,7 @@ void SynEditTextPainter::PaintLines()
colSelFG = edit->mSelectedForeground;
colSelBG = edit->mSelectedBackground;
}
edit->DoOnEditAreas(vLine, areaList);
edit->onEditingAreas(vLine, areaList);
// Removed word wrap support
vFirstChar = FirstCol;
vLastChar = LastCol;
@ -536,26 +803,26 @@ void SynEditTextPainter::PaintLines()
rcToken = rcLine;
if (!edit->mHighlighter || !edit->mHighlighter->enabled()) {
sToken = sLine;
nTokenLen = edit->mLines->lineColumns(vLine-1);
if (edit->mShowSpecChar && (!bLineSelected) && (!bSpecialLine) && (nTokenLen < vLastChar)) {
nTokenColumnLen = edit->mLines->lineColumns(vLine-1);
if (edit->mShowSpecChar && (!bLineSelected) && (!bSpecialLine) && (nTokenColumnLen < vLastChar)) {
sToken = sToken + SynLineBreakGlyph;
nTokenLen = sToken + edit->charColumns(SynLineBreakGlyph);
nTokenColumnLen += 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);
PaintToken(sToken, nTokenColumnLen, 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);
PaintToken(sToken, nTokenColumnLen, 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);
PaintToken(sToken, nTokenColumnLen, 0, nLineSelStart, nLineSelEnd - 1,false);
} else {
setDrawingColors(bLineSelected);
PaintToken(sToken, nTokenLen, 0, FirstCol, LastCol,bLineSelected);
PaintToken(sToken, nTokenColumnLen, 0, FirstCol, LastCol,bLineSelected);
}
} else {
// Initialize highlighter with line text and range info. It is
@ -577,7 +844,7 @@ void SynEditTextPainter::PaintLines()
// or the line having special colors. For spaces the foreground color
// is ignored as well.
TokenAccu.Columns = 0;
nTokenPos = 0;
nTokenStartColumn = 0;
// Test first whether anything of this token is visible.
while (edit->mHighlighter->eol()) {
sToken = edit->mHighlighter->getToken();
@ -591,13 +858,13 @@ void SynEditTextPainter::PaintLines()
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)
nTokenStartColumn = edit->charToColumn(vLine,edit->mHighlighter->getTokenPos());
nTokenColumnLen = edit->stringColumns(sToken, nTokenStartColumn-1);
if (nTokenStartColumn + nTokenColumnLen >= vFirstChar) {
if (nTokenStartColumn + nTokenColumnLen >= vLastChar) {
if (nTokenStartColumn >= vLastChar)
break; //*** BREAK ***
nTokenLen = vLastChar - nTokenPos - 1;
nTokenColumnLen = vLastChar - nTokenStartColumn - 1;
}
// It's at least partially visible. Get the token attributes now.
attr = edit->mHighlighter->getTokenAttribute();
@ -614,25 +881,25 @@ void SynEditTextPainter::PaintLines()
} else if (sToken == "}") {
GetBraceColorAttr(edit->mHighlighter->getBraceLevel()+1,attr);
}
AddHighlightToken(sToken, nTokenPos - (vFirstChar - FirstCol),
nTokenLen, vLine,attr);
AddHighlightToken(sToken, nTokenStartColumn - (vFirstChar - FirstCol),
nTokenColumnLen, 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)) {
nTokenStartColumn += edit->stringColumns(sToken,nTokenStartColumn-1);
if (edit->mHighlighter->eol() && (nTokenStartColumn < 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());
if (nTokenStartColumn < lineColumns) {
if (nTokenStartColumn + 1 < vFirstChar)
nTokenStartColumn = vFirstChar - 1;
nTokenColumnLen = std::min(lineColumns, vLastChar) - (nTokenStartColumn + 1);
if (nTokenColumnLen > 0) {
sToken = edit->substringByColumns(sLine,nTokenStartColumn+1,nTokenColumnLen);
AddHighlightToken(sToken, nTokenStartColumn - (vFirstChar - FirstCol),
nTokenColumnLen, vLine, PSynHighlighterAttribute());
}
}
// Draw LineBreak glyph.
@ -647,12 +914,12 @@ void SynEditTextPainter::PaintLines()
// 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);
sFold = " ... } ";
nFold = edit->stringColumns(sFold,edit->mLines->lineColumns(vLine-1));
attr = edit->mHighlighter->symbolAttribute();
GetBraceColorAttr(edit->mHighlighter->getBraceLevel(),attr);
AddHighlightToken(sFold,edit->mLines->lineColumns(vLine-1)+1 - (vFirstChar - FirstCol)
, nFold, vLine, attr);
}
// Draw anything that's left in the TokenAccu record. Fill to the end
@ -667,10 +934,15 @@ void SynEditTextPainter::PaintLines()
// 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);
painter->drawLine(nRightEdge, rcLine.top(),nRightEdge,rcLine.bottom()+1);
}
bCurrentLine = false;
}
}
void SynEditTextPainter::drawMark(PSynEditMark aMark, int &aGutterOff, int aMarkRow)
{
//todo
}

View File

@ -7,6 +7,7 @@
#include "Types.h"
#include "highlighter/base.h"
#include "../utils.h"
#include "MiscClasses.h"
class SynEdit;
class SynEditTextPainter
@ -21,15 +22,19 @@ class SynEditTextPainter
};
public:
SynEditTextPainter(SynEdit * edit);
SynEditTextPainter(SynEdit * edit,int FirstRow, int LastRow,
int FirstCol, int LastCol);
void paintTextLines(const QRect& clip);
void paintGutter(const QRect& clip);
private:
QColor colEditorBG();
void ComputeSelectionInfo();
void setDrawingColors(bool Selected);
int ColumnToXValue(int Col);
void PaintToken(const QString& Token, int TokenLen, int ColumnsBefore,
int First, int Last, bool isSelection);
void PaintEditAreas(PSynEditingAreaList areaList);
void PaintEditAreas(const SynEditingAreaList& areaList);
void PaintHighlightToken(bool bFillToEOL);
bool TokenIsSpaces(bool& bSpacesTest, const QString& Token, bool& bIsSpaces);
void AddHighlightToken(const QString& Token, int ColumnsBefore, int TokenColumns,
@ -38,6 +43,8 @@ public:
void PaintFoldAttributes();
void GetBraceColorAttr(int level, PSynHighlighterAttribute &attr);
void PaintLines();
void drawMark(PSynEditMark aMark,int& aGutterOff, int aMarkRow);
private:
SynEdit* edit;
QPainter* painter;

View File

@ -350,3 +350,16 @@ void decodeKey(const int combinedKey, int &key, Qt::KeyboardModifiers &modifiers
}
key = combinedKey & ~(Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier);
}
void inflateRect(QRect &rect, int delta)
{
inflateRect(rect,delta,delta);
}
void inflateRect(QRect &rect, int dx, int dy)
{
rect.setLeft(rect.left()-dx);
rect.setRight(rect.right()+dx);
rect.setTop(rect.top()-dy);
rect.setBottom(rect.bottom()+dy);
}

View File

@ -5,6 +5,7 @@
#include <utility>
#include <functional>
#include <QString>
#include <QRect>
class QByteArray;
class QString;
@ -92,6 +93,9 @@ void ReadFileToLines(const QString& fileName, QTextCodec* codec, LineProcessFunc
void decodeKey(int combinedKey, int& key, Qt::KeyboardModifiers& modifiers);
void inflateRect(QRect& rect, int delta);
void inflateRect(QRect& rect, int dx, int dy);
template <class F>
class final_action
{