fix: font style not correct when painting

This commit is contained in:
Roy Qu 2024-02-25 18:59:39 +08:00
parent 16053882d4
commit 9672ebd079
10 changed files with 849 additions and 599 deletions

View File

@ -17,6 +17,8 @@ APP_NAME = RedPandaCPP
APP_VERSION = 2.27
APP_VERSION_SUFFIX = alpha
# TEST_VERSION = beta2
system(git rev-list HEAD --count): TEST_VERSION = $$system(git rev-list HEAD --count)
@ -57,9 +59,9 @@ DEFINES += PREFIX=\\\"$${PREFIX}\\\"
DEFINES += LIBEXECDIR=\\\"$${LIBEXECDIR}\\\"
DEFINES += APP_NAME=\\\"$${APP_NAME}\\\"
isEmpty(TEST_VERSION) {
DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}\\\"
DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}$${APP_VERSION_SUFFIX}\\\"
} else {
DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}.$${TEST_VERSION}\\\"
DEFINES += REDPANDA_CPP_VERSION=\\\"$${APP_VERSION}$${APP_VERSION_SUFFIX}.$${TEST_VERSION}\\\"
}
win32 {
_WINDOWS_PREFER_OPENCONSOLE = $$(WINDOWS_PREFER_OPENCONSOLE)

View File

@ -5159,10 +5159,6 @@
<source>Toggle Readonly</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Line: %1 Col: %2 Lines: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Newline</source>
<translation type="unfinished"></translation>
@ -5420,7 +5416,11 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Line: %1 Col: %2 Sel:%3 Lines: %4</source>
<source>Line: %1 Char: %2 Sel:%3 Lines: %4</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Line: %1 Char: %2 Lines: %3</source>
<translation type="unfinished"></translation>
</message>
</context>

File diff suppressed because it is too large Load Diff

View File

@ -4868,10 +4868,6 @@
<source>Toggle Readonly</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Line: %1 Col: %2 Lines: %3</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Newline</source>
<translation type="unfinished"></translation>
@ -5133,7 +5129,11 @@
<translation type="unfinished"></translation>
</message>
<message>
<source>Line: %1 Col: %2 Sel:%3 Lines: %4</source>
<source>Line: %1 Char: %2 Sel:%3 Lines: %4</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Line: %1 Char: %2 Lines: %3</source>
<translation type="unfinished"></translation>
</message>
</context>

View File

@ -21,8 +21,6 @@ qsynedit.depends = redpanda_qt_utils
APP_NAME = RedPandaCPP
APP_VERSION = 2.27
win32: {
SUBDIRS += \
redpanda-win-git-askpass

View File

@ -895,6 +895,14 @@ int Document::stringWidth(const QString &str, int left) const
return right - left;
}
int Document::stringWidth(const QString &str, int left, const QFontMetrics &asciFontMetrics, const QFontMetrics &nonAsciiFontMetrics)
{
QList<int> glyphStartCharList = calcGlyphStartCharList(str);
int right;
calcGlyphPositionList(str, glyphStartCharList, asciFontMetrics, nonAsciiFontMetrics, left, right);
return right - left;
}
int Document::glyphCount(int line)
{
QMutexLocker locker(&mMutex);
@ -929,20 +937,7 @@ int Document::glyphWidth(int line, int glyphIdx)
int Document::glyphWidth(const QString &glyph, int left) const
{
int glyphWidth;
if (glyph.length()==1 && glyph[0].unicode()<0xFF) {
QChar ch = glyph[0];
if (ch == '\t') {
glyphWidth = tabWidth() - left % tabWidth();
} else {
glyphWidth = mFontMetrics.horizontalAdvance(ch);
//qDebug()<<glyph<<glyphCols<<width<<mCharWidth;
}
} else {
glyphWidth = mNonAsciiFontMetrics.horizontalAdvance(glyph);
//qDebug()<<glyph<<glyphCols<<width<<mCharWidth;
}
return glyphWidth;
return glyphWidth(glyph,left,mFontMetrics, mNonAsciiFontMetrics);
}
int Document::charToGlyphIndex(int line, int charIdx)
@ -975,12 +970,33 @@ QList<int> Document::calcLineWidth(const QString &lineText, const QList<int> &gl
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
}
QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics, int left, int &right) const
{
right = std::max(0,left);
int start,end;
QList<int> glyphPostionList;
for (int i=0;i<glyphStartCharList.length();i++) {
start = glyphStartCharList[i];
if (i+1<glyphStartCharList.length()) {
end = glyphStartCharList[i+1];
} else {
end = lineText.length();
}
QString glyph = lineText.mid(start,end-start);
int gWidth = glyphWidth(glyph, right, fontMetrics, nonAsciiFontMetrics);
glyphPostionList.append(right);
right += gWidth;
}
return glyphPostionList;
}
int Document::xposToGlyphIndex(int line, int xpos)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return 0;
QList<int> glyphPositionList = mLines[line]->glyphPositionList();
QList<int> glyphPositionList = mLines[line]->glyphStartPositionList();
return xposToGlyphIndex(mLines[line]->width(), glyphPositionList, xpos);
}
@ -1010,7 +1026,7 @@ int Document::xposToGlyphStartChar(int line, int xpos)
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return 0;
QList<int> glyphPositionList = mLines[line]->glyphPositionList();
QList<int> glyphPositionList = mLines[line]->glyphStartPositionList();
int glyphIdx = xposToGlyphIndex(mLines[line]->width(), glyphPositionList, xpos);
return mLines[line]->glyphStartChar(glyphIdx);
}
@ -1040,7 +1056,7 @@ int Document::xposToGlyphStartChar(int line, const QString newStr, int xpos)
QList<int> glyphPositionList;
int width;
if (mLines[line]->lineText() == newStr) {
glyphPositionList = mLines[line]->glyphPositionList();
glyphPositionList = mLines[line]->glyphStartPositionList();
width = mLines[line]->width();
} else {
glyphPositionList = calcGlyphPositionList(mLines[line]->lineText(), width);
@ -1124,24 +1140,24 @@ void Document::internalClear()
}
}
void Document::setLineWidth(int line, const QString &lineText, int newWidth, const QList<int> glyphStartPositionList)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return ;
if (lineText != mLines[line]->lineText())
return;
mLines[line]->mWidth = newWidth;
mLines[line]->mGlyphStartPositionList = glyphStartPositionList;
Q_ASSERT(mLines[line]->mGlyphStartPositionList.length() == mLines[line]->mGlyphStartCharList.length());
}
QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<int> &glyphStartCharList, int left, int &right) const
{
right = std::max(0,left);
int start,end;
QList<int> glyphPostionList;
for (int i=0;i<glyphStartCharList.length();i++) {
start = glyphStartCharList[i];
if (i+1<glyphStartCharList.length()) {
end = glyphStartCharList[i+1];
} else {
end = lineText.length();
}
QString glyph = lineText.mid(start,end-start);
int gWidth = glyphWidth(glyph, right);
glyphPostionList.append(right);
right += gWidth;
}
return glyphPostionList;
return calcGlyphPositionList(lineText, glyphStartCharList,
mFontMetrics,
mNonAsciiFontMetrics,
left,right);
}
@ -1151,6 +1167,21 @@ QList<int> Document::calcGlyphPositionList(const QString &lineText, int &width)
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
}
QList<int> Document::getGlyphStartCharList(int line, const QString &lineText)
{
if (line<0 || line>=count() || mLines[line]->lineText()!=lineText)
return calcGlyphStartCharList(lineText);
return mLines[line]->glyphStartCharList();
}
QList<int> Document::getGlyphStartPositionList(int line, const QString &lineText, int &lineWidth)
{
if (line<0 || line>=count() || mLines[line]->lineText()!=lineText)
return calcGlyphPositionList(lineText,lineWidth);
lineWidth = mLines[line]->width();
return mLines[line]->glyphStartPositionList();
}
NewlineType Document::getNewlineType()
{
QMutexLocker locker(&mMutex);
@ -1212,21 +1243,21 @@ int DocumentLine::glyphStartPosition(int i)
return 0;
if (mWidth<0)
updateWidth();
if (i>=mGlyphPositionList.length())
if (i>=mGlyphStartPositionList.length())
return mWidth;
return mGlyphPositionList[i];
return mGlyphStartPositionList[i];
}
int DocumentLine::glyphWidth(int i)
{
if (i<0 || i>=mGlyphPositionList.length())
if (i<0 || i>=mGlyphStartPositionList.length())
return 0;
if( mWidth <0)
updateWidth();
int start = glyphStartPosition(i);
int end;
if (i+1<mGlyphPositionList.length()) {
end = mGlyphPositionList[i+1];
if (i+1<mGlyphStartPositionList.length()) {
end = mGlyphStartPositionList[i+1];
} else {
end = mWidth;
}
@ -1250,15 +1281,15 @@ void DocumentLine::setLineText(const QString &newLineText)
void DocumentLine::updateWidth()
{
Q_ASSERT(mUpdateWidthFunc!=nullptr);
mGlyphPositionList = mUpdateWidthFunc(mLineText, mGlyphStartCharList, mWidth);
mGlyphStartPositionList = mUpdateWidthFunc(mLineText, mGlyphStartCharList, mWidth);
// qDebug()<<"Update Width"<<mLineText<<mWidth<<mGlyphPositionList;
}
const QList<int> &DocumentLine::glyphPositionList()
const QList<int> &DocumentLine::glyphStartPositionList()
{
if(mWidth<0)
updateWidth();
return mGlyphPositionList;
return mGlyphStartPositionList;
}
int DocumentLine::glyphStartChar(int i) const
@ -1703,4 +1734,64 @@ int searchForSegmentIdx(const QList<int> segList, int minVal, int maxVal, int va
return -1;
}
int Document::updateGlyphStartPositionList(
const QString &lineText,
const QList<int> &glyphStartCharList, int startChar, int endChar,
const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics,
QList<int> &glyphStartPositionList, int left, int &right, int &startGlyph, int &endGlyph) const
{
right = std::max(0,left);
startGlyph = searchForSegmentIdx(glyphStartCharList,0,lineText.length(),startChar);
endGlyph = searchForSegmentIdx(glyphStartCharList,0,lineText.length(),endChar);
for (int i=startGlyph;i<endGlyph;i++) {
int start = glyphStartCharList[i];
int end;
if (i+1<glyphStartCharList.length()) {
end = glyphStartCharList[i+1];
} else {
end = lineText.length();
}
QString glyph = lineText.mid(start,end-start);
int gWidth = glyphWidth(glyph, right, fontMetrics, nonAsciiFontMetrics);
glyphStartPositionList[i] = right;
right += gWidth;
}
return right-left;
}
int Document::glyphWidth(const QString &glyph, int left, const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics) const
{
int glyphWidth;
if (glyph.length()==1 && glyph[0].unicode()<0xFF) {
QChar ch = glyph[0];
if (ch == '\t') {
glyphWidth = tabWidth() - left % tabWidth();
} else {
glyphWidth = fontMetrics.horizontalAdvance(ch);
//qDebug()<<glyph<<glyphCols<<width<<mCharWidth;
}
} else {
glyphWidth = nonAsciiFontMetrics.horizontalAdvance(glyph);
//qDebug()<<glyph<<glyphCols<<width<<mCharWidth;
}
return glyphWidth;
}
void expandGlyphStartCharList(const QString &strAdded, int oldStrLen, QList<int> glyphStartCharList)
{
QList<int> addedList = calcGlyphStartCharList(strAdded);
for (int i=0;i<addedList.length();i++) {
glyphStartCharList.append(addedList[i]+oldStrLen);
}
}
int calcSegmentInterval(const QList<int> segList, int maxVal, int idx)
{
if (idx<0 || idx>=segList.length())
return 0;
if (idx == segList.length()-1)
return maxVal - segList[idx];
return segList[idx+1]-segList[idx];
}
}

View File

@ -31,8 +31,9 @@
namespace QSynedit {
int searchForSegmentIdx(const QList<int> segList, int minVal, int maxVal, int value);
int calcSegmentInterval(const QList<int> segList, int maxVal, int idx);
QList<int> calcGlyphStartCharList(const QString &text);
void expandGlyphStartCharList(const QString& strAdded, int oldStrLen, QList<int> glyphStartCharList);
class Document;
@ -83,7 +84,7 @@ private:
* @brief get list of start position of the glyphs in the line text
* @return start positions of the glyph (in pixel)
*/
const QList<int>& glyphPositionList();
const QList<int>& glyphStartPositionList();
/**
* @brief get start index of the chars representing the specified glyph.
@ -145,7 +146,7 @@ private:
void setLineText(const QString &newLineText);
void updateWidth();
void invalidateWidth() { mWidth = -1; mGlyphPositionList.clear(); }
void invalidateWidth() { mWidth = -1; mGlyphStartPositionList.clear(); }
private:
QString mLineText; /* the unicode code points of the text */
/**
@ -160,11 +161,11 @@ private:
* @brief start columns of the glyphs
*
* A glyph may occupy more than one columns in the screen.
* Each elements of mGlyphPositionList is the columns occupied by the glyph.
* Each elements of mGlyphStartPositionList is the columns occupied by the glyph.
* The width of a glyph is affected by the font used to display,
* so it must be recalculated each time the font is changed.
*/
QList<int> mGlyphPositionList;
QList<int> mGlyphStartPositionList;
/**
* @brief state of the syntax highlighter after this line is parsed
*
@ -441,6 +442,8 @@ public:
*/
int stringWidth(const QString &str, int left) const;
int stringWidth(const QString &str, int left, const QFontMetrics &asciFontMetrics, const QFontMetrics &nonAsciiFontMetrics);
int glyphCount(int line);
/**
* @brief get start index of the chars representing the specified glyph in the specified line.
@ -515,6 +518,14 @@ public:
int charToGlyphStartPosition(int line, const QString newStr, int charPos);
int xposToGlyphStartChar(int line, const QString newStr, int xpos);
int updateGlyphStartPositionList(
const QString& lineText,
const QList<int> &glyphStartCharList,
int startChar, int endChar,
const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics,
QList<int> &glyphStartPositionList,
int left, int &right, int &startGlyph, int &endGlyph) const;
bool getAppendNewLineAtEOF();
void setAppendNewLineAtEOF(bool appendNewLineAtEOF);
@ -554,11 +565,22 @@ protected:
void putTextStr(const QString& text);
void internalClear();
private:
void setLineWidth(int line, const QString& lineText, int newWidth, const QList<int> glyphStartPositionList);
int glyphWidth(const QString& glyph, int left,
const QFontMetrics &fontMetrics, const QFontMetrics &nonAsciiFontMetrics) const;
int xposToGlyphIndex(int strWidth, QList<int> glyphPositionList, int xpos) const;
int charToGlyphIndex(const QString& str, QList<int> glyphStartCharList, int charPos) const;
QList<int> calcLineWidth(const QString& lineText, const QList<int> &glyphStartCharList, int &width);
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList,
const QFontMetrics &fontMetrics,
const QFontMetrics &nonAsciiFontMetrics,
int left, int &right) const;
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList, int left, int &right) const;
QList<int> calcGlyphPositionList(const QString& lineText, int &width) const;
QList<int> getGlyphStartCharList(int line, const QString &lineText);
QList<int> getGlyphStartPositionList(int line, const QString &lineText, int &lineWidth);
bool tryLoadFileByEncoding(QByteArray encodingName, QFile& file);
void loadUTF16BOMFile(QFile& file);
void loadUTF32BOMFile(QFile& file);
@ -588,6 +610,8 @@ private:
#else
QMutex mMutex;
#endif
friend class QSynEditPainter;
};
enum class ChangeReason {

View File

@ -354,7 +354,12 @@ int QSynEditPainter::fixXValue(int xpos)
}
void QSynEditPainter::paintToken(
const QString &token, int tokenWidth, int tokenLeft,
const QString& lineText,
const QList<int> &glyphStartCharList,
const QList<int> &glyphStartPositionList,
int startGlyph,
int endGlyph,
int tokenWidth, int tokenLeft,
int first, int last, bool /*isSelection*/, const QFont& font,
const QFont& fontForNonAscii, bool showGlyphs)
{
@ -362,8 +367,12 @@ void QSynEditPainter::paintToken(
int nX;
bool lastGlyphAscii = false;
bool fontInited = false;
int tokenRight = tokenWidth+tokenLeft;
// qDebug()<<"Paint token"<<token<<tokenWidth<<tokenLeft<<first<<last<<rcToken;
//qDebug()<<"Paint token"<<lineText<<tokenWidth<<tokenLeft<<first<<last<<rcToken;
// qDebug()<<glyphStartCharList;
// qDebug()<<glyphStartPositionList;
// qDebug()<<startGlyph<<endGlyph;
if (last >= first && rcToken.right() > rcToken.left()) {
nX = fixXValue(first);
@ -375,14 +384,12 @@ void QSynEditPainter::paintToken(
} else {
int tokenWidth=0;
startPaint = false;
QList<int> glyphStartCharList = calcGlyphStartCharList(token);
// qDebug()<<"painting:"<<token;
for (int i=0; i< glyphStartCharList.length();i++) {
for (int i=startGlyph; i<endGlyph;i++) {
int glyphStart = glyphStartCharList[i];
int glyphEnd =(i+1<glyphStartCharList.length())?glyphStartCharList[i+1]:token.length();
QString glyph = token.mid(glyphStart,glyphEnd-glyphStart);
int glyphWidth = mEdit->document()->glyphWidth(glyph, tokenLeft+tokenWidth);
// qDebug()<<glyph<<charCols;
int glyphLen = calcSegmentInterval(glyphStartCharList,lineText.length(),i);
QString glyph = lineText.mid(glyphStart,glyphLen);
int glyphWidth = calcSegmentInterval(glyphStartPositionList, tokenRight, i);
// qDebug()<<"painting:"<<glyph<<glyphWidth<<tokenWidth+glyphWidth<<first<<last;
if (tokenWidth+glyphWidth>first) {
if (!startPaint ) {
nX-= (first - tokenWidth - 1) ;
@ -410,8 +417,8 @@ void QSynEditPainter::paintToken(
QString textToPaint = glyph;
while(i+1<glyphStartCharList.length()) {
int glyphStart = glyphStartCharList[i+1];
int glyphEnd =(i+2<glyphStartCharList.length())?glyphStartCharList[i+2]:token.length();
QString glyph2 = token.mid(glyphStart,glyphEnd-glyphStart);
int glyphLen = calcSegmentInterval(glyphStartCharList,lineText.length(),i+1);
QString glyph2 = lineText.mid(glyphStart,glyphLen);
// if (!OperatorGlyphs.contains(glyph))
// break;
if (isAscii) {
@ -428,7 +435,7 @@ void QSynEditPainter::paintToken(
break;
}
i+=1;
glyphWidth += mEdit->document()->glyphWidth(glyph2,0);
glyphWidth += calcSegmentInterval(glyphStartPositionList, tokenLeft+tokenWidth, i);
textToPaint+=glyph2;
if (tokenWidth + glyphWidth > last )
break;
@ -544,7 +551,10 @@ void QSynEditPainter::paintEditAreas(const EditingAreaList &areaList)
}
}
void QSynEditPainter::paintHighlightToken(bool bFillToEOL)
void QSynEditPainter::paintHighlightToken(const QString& lineText,
const QList<int> &glyphStartCharList,
const QList<int> &glyphStartPositionsList,
bool bFillToEOL)
{
bool isComplexToken;
int nC1, nC2, nC1Sel, nC2Sel;
@ -578,16 +588,7 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL)
// if (bSpecialLine && mEdit->mOptions.testFlag(eoSpecialLineDefaultFg))
// colFG = TokenAccu.FG;
QFont font = mEdit->font();
font.setBold(mTokenAccu.style & FontStyle::fsBold);
font.setItalic(mTokenAccu.style & FontStyle::fsItalic);
font.setStrikeOut(mTokenAccu.style & FontStyle::fsStrikeOut);
font.setUnderline(mTokenAccu.style & FontStyle::fsUnderline);
QFont nonAsciiFont = mEdit->fontForNonAscii();
nonAsciiFont.setBold(mTokenAccu.style & FontStyle::fsBold);
nonAsciiFont.setItalic(mTokenAccu.style & FontStyle::fsItalic);
nonAsciiFont.setStrikeOut(mTokenAccu.style & FontStyle::fsStrikeOut);
nonAsciiFont.setUnderline(mTokenAccu.style & FontStyle::fsUnderline);
// Paint the chars
if (isComplexToken) {
@ -596,24 +597,47 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL)
setDrawingColors(false);
rcToken.setRight(fixXValue(mLineSelStart));
paintToken(
mTokenAccu.s,mTokenAccu.width,mTokenAccu.left,nC1,mLineSelStart,false,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs);
lineText,
glyphStartCharList,
glyphStartPositionsList,
mTokenAccu.startGlyph,
mTokenAccu.endGlyph,
mTokenAccu.width,mTokenAccu.left,nC1,mLineSelStart,false,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs);
}
// selected part of the token
setDrawingColors(true);
nC1Sel = std::max(mLineSelStart, nC1);
nC2Sel = std::min(mLineSelEnd, nC2);
rcToken.setRight(fixXValue(nC2Sel));
paintToken(mTokenAccu.s, mTokenAccu.width, mTokenAccu.left, nC1Sel, nC2Sel,true,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs);
paintToken(
lineText,
glyphStartCharList,
glyphStartPositionsList,
mTokenAccu.startGlyph,
mTokenAccu.endGlyph,
mTokenAccu.width, mTokenAccu.left, nC1Sel, nC2Sel,true,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs);
// second unselected part of the token
if (bU2) {
setDrawingColors(false);
rcToken.setRight(fixXValue(nC2));
paintToken(mTokenAccu.s, mTokenAccu.width, mTokenAccu.left, mLineSelEnd, nC2,false,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs);
paintToken(
lineText,
glyphStartCharList,
glyphStartPositionsList,
mTokenAccu.startGlyph,
mTokenAccu.endGlyph,
mTokenAccu.width, mTokenAccu.left, mLineSelEnd, nC2,false,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs);
}
} else {
setDrawingColors(bSel);
rcToken.setRight(fixXValue(nC2));
paintToken(mTokenAccu.s, mTokenAccu.width, mTokenAccu.left, nC1, nC2,bSel,font,nonAsciiFont, mTokenAccu.showSpecialGlyphs);
paintToken(
lineText,
glyphStartCharList,
glyphStartPositionsList,
mTokenAccu.startGlyph,
mTokenAccu.endGlyph,
mTokenAccu.width, mTokenAccu.left, nC1, nC2,bSel,mTokenAccu.font,mTokenAccu.nonAsciiFont, mTokenAccu.showSpecialGlyphs);
}
}
@ -658,9 +682,15 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL)
// 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 QSynEditPainter::addHighlightToken(const QString &token, int tokenLeft,
int tokenWidth, int line, PTokenAttribute attri,
bool showGlyphs)
void QSynEditPainter::addHighlightToken(
const QString& lineText,
const QString& token, int tokenLeft,
int line, PTokenAttribute attri, bool showGlyphs,
const QList<int> glyphStartCharList,
int tokenStartChar,
int tokenEndChar,
QList<int> &glyphStartPositionList,
int &tokenWidth)
{
bool bCanAppend;
QColor foreground, background;
@ -706,21 +736,53 @@ void QSynEditPainter::addHighlightToken(const QString &token, int tokenLeft,
}
// If we can't append it, then we have to paint the old token chars first.
if (!bCanAppend)
paintHighlightToken(false);
paintHighlightToken(lineText, glyphStartCharList, glyphStartPositionList, false);
}
// Don't use AppendStr because it's more expensive.
if (!bCanAppend) {
mTokenAccu.font = mEdit->font();
mTokenAccu.font.setBold(style & FontStyle::fsBold);
mTokenAccu.font.setItalic(style & FontStyle::fsItalic);
mTokenAccu.font.setStrikeOut(style & FontStyle::fsStrikeOut);
mTokenAccu.font.setUnderline(style & FontStyle::fsUnderline);
mTokenAccu.nonAsciiFont = mEdit->fontForNonAscii();
mTokenAccu.nonAsciiFont.setBold(style & FontStyle::fsBold);
mTokenAccu.nonAsciiFont.setItalic(style & FontStyle::fsItalic);
mTokenAccu.nonAsciiFont.setStrikeOut(style & FontStyle::fsStrikeOut);
mTokenAccu.nonAsciiFont.setUnderline(style & FontStyle::fsUnderline);
}
//calculate width of the token ( and update it's glyph start positions )
int tokenRight;
int startGlyph, endGlyph;
tokenWidth = mEdit->mDocument->updateGlyphStartPositionList(
lineText,
glyphStartCharList,
tokenStartChar,
tokenEndChar,
QFontMetrics(mTokenAccu.font),
QFontMetrics(mTokenAccu.nonAsciiFont),
glyphStartPositionList,
tokenLeft,
tokenRight,
startGlyph,
endGlyph);
// Only accumulate tokens if it's visible.
if (tokenLeft < mRight) {
if (bCanAppend) {
mTokenAccu.s.append(token);
mTokenAccu.width+=tokenWidth;
mTokenAccu.width += tokenWidth;
Q_ASSERT(startGlyph == mTokenAccu.endGlyph);
mTokenAccu.endGlyph = endGlyph;
} else {
mTokenAccu.width = tokenWidth;
mTokenAccu.s = token;
mTokenAccu.left = tokenLeft;
mTokenAccu.startGlyph = startGlyph;
mTokenAccu.endGlyph = endGlyph;
mTokenAccu.foreground = foreground;
mTokenAccu.background = background;
mTokenAccu.style = style;
mTokenAccu.showSpecialGlyphs = showGlyphs;
}
}
}
void QSynEditPainter::paintFoldAttributes()
@ -864,8 +926,6 @@ void QSynEditPainter::paintLines()
EditingAreaList areaList;
PCodeFoldingRange foldRange;
PTokenAttribute preeditAttr;
int nFold;
QString sFold;
// Initialize rcLine for drawing. Note that Top and Bottom are updated
// inside the loop. Get only the starting point for this.
@ -950,32 +1010,60 @@ void QSynEditPainter::paintLines()
mIsLineSelected = (!mIsComplexLine) && (mLineSelStart > 0);
rcToken = rcLine;
int lineWidth;
QList<int> glyphStartCharList = mEdit->mDocument->getGlyphStartCharList(vLine-1,sLine);
QList<int> glyphStartPositionsList = mEdit->mDocument->getGlyphStartPositionList(vLine-1,sLine, lineWidth);
if (!mEdit->mSyntaxer || !mEdit->mSyntaxer->enabled()) {
sToken = sLine;
if (mIsCurrentLine) {
tokenWidth = mEdit->document()->lineWidth(vLine-1, sLine);
} else {
tokenWidth = mEdit->document()->lineWidth(vLine-1);
}
tokenWidth = lineWidth;
if (mEdit->mOptions.testFlag(eoShowLineBreaks) && (!mIsLineSelected) && (!mIsSpecialLine) && (tokenWidth <= mLeft)) {
sToken = sToken + LineBreakGlyph;
tokenWidth += mEdit->document()->glyphWidth(LineBreakGlyph,0);
expandGlyphStartCharList(LineBreakGlyph, sLine.length(), glyphStartCharList);
int width = mEdit->document()->glyphWidth(LineBreakGlyph,0);
glyphStartPositionsList.append(tokenWidth);
sLine+=LineBreakGlyph;
tokenWidth += width;
}
if (mIsComplexLine) {
setDrawingColors(true);
rcToken.setLeft(std::max(rcLine.left(), fixXValue(mLineSelStart)));
rcToken.setRight(std::min(rcLine.right(), fixXValue(mLineSelEnd)));
paintToken(sToken, tokenWidth, 0, mLineSelStart, mLineSelEnd,false,mEdit->font(),mEdit->fontForNonAscii(),false);
paintToken(
sLine,
glyphStartCharList,
glyphStartPositionsList,
0,
glyphStartCharList.length(),
tokenWidth, 0, mLineSelStart, mLineSelEnd,false,mEdit->font(),mEdit->fontForNonAscii(),false);
setDrawingColors(false);
rcToken.setLeft(std::max(rcLine.left(), fixXValue(mLeft)));
rcToken.setRight(std::min(rcLine.right(), fixXValue(mLineSelStart)));
paintToken(sToken, tokenWidth, 0, mLeft, mLineSelStart,false,mEdit->font(),mEdit->fontForNonAscii(),false);
paintToken(
sLine,
glyphStartCharList,
glyphStartPositionsList,
0,
glyphStartCharList.length(),
tokenWidth, 0, mLeft, mLineSelStart,false,mEdit->font(),mEdit->fontForNonAscii(),false);
rcToken.setLeft(std::max(rcLine.left(), fixXValue(mLineSelEnd)));
rcToken.setRight(std::min(rcLine.right(), fixXValue(mRight)));
paintToken(sToken, tokenWidth, 0, mLineSelEnd, mRight,true, mEdit->font(), mEdit->fontForNonAscii(),false);
paintToken(
sLine,
glyphStartCharList,
glyphStartPositionsList,
0,
glyphStartCharList.length(),
tokenWidth, 0, mLineSelEnd, mRight,true, mEdit->font(), mEdit->fontForNonAscii(),false);
} else {
setDrawingColors(mIsLineSelected);
paintToken(sToken, tokenWidth, 0, mLeft, mRight, mIsLineSelected,mEdit->font(),mEdit->fontForNonAscii(),false);
paintToken(
sLine,
glyphStartCharList,
glyphStartPositionsList,
0,
glyphStartCharList.length(),
tokenWidth, 0, mLeft, mRight, mIsLineSelected,mEdit->font(),mEdit->fontForNonAscii(),false);
}
//Paint editingAreaBorders
if (mIsCurrentLine && mEdit->mInputPreeditString.length()>0) {
@ -1007,26 +1095,21 @@ void QSynEditPainter::paintLines()
// Test first whether anything of this token is visible.
while (!mEdit->mSyntaxer->eol()) {
sToken = mEdit->mSyntaxer->getToken();
// Work-around buggy highlighters which return empty tokens.
if (sToken.isEmpty()) {
mEdit->mSyntaxer->next();
if (mEdit->mSyntaxer->eol())
break;
sToken = mEdit->mSyntaxer->getToken();
// Maybe should also test whether GetTokenPos changed...
if (sToken.isEmpty()) {
//qDebug()<<QSynEdit::tr("The highlighter seems to be in an infinite loop");
throw BaseError(QSynEdit::tr("The syntaxer seems to be in an infinite loop"));
}
}
//nTokenColumnsBefore = edit->charToColumn(sLine,edit->mHighlighter->getTokenPos()+1)-1;
tokenWidth = mEdit->stringWidth(sToken, tokenLeft);
if ( tokenLeft + tokenWidth >= mLeft) {
if (tokenLeft + tokenWidth >= mRight) {
if (tokenLeft >= mRight)
break; //*** BREAK ***
tokenWidth = mRight - tokenLeft;
continue;
// mEdit->mSyntaxer->next();
// if (mEdit->mSyntaxer->eol())
// break;
// sToken = mEdit->mSyntaxer->getToken();
// // Maybe should also test whether GetTokenPos changed...
// if (sToken.isEmpty()) {
// //qDebug()<<QSynEdit::tr("The highlighter seems to be in an infinite loop");
// throw BaseError(QSynEdit::tr("The syntaxer seems to be in an infinite loop"));
// }
}
int tokenStartChar = mEdit->mSyntaxer->getTokenPos();
int tokenEndChar = tokenStartChar + sToken.length();
// It's at least partially visible. Get the token attributes now.
attr = mEdit->mSyntaxer->getTokenAttribute();
@ -1075,37 +1158,61 @@ void QSynEditPainter::paintLines()
showGlyph = mEdit->mOptions.testFlag(eoShowInnerSpaces);
}
}
addHighlightToken(sToken, tokenLeft,
tokenWidth, vLine,attr, showGlyph);
}
addHighlightToken(
sLine,
sToken,
tokenLeft,
vLine, attr,showGlyph,
glyphStartCharList,
tokenStartChar,
tokenEndChar,
glyphStartPositionsList,
tokenWidth);
tokenLeft+=tokenWidth;
// Let the highlighter scan the next token.
mEdit->mSyntaxer->next();
}
mEdit->mDocument->setLineWidth(vLine-1, sLine, tokenLeft, glyphStartPositionsList);
if (tokenLeft<mRight) {
QString addOnStr;
// Paint folding
foldRange = mEdit->foldStartAtLine(vLine);
if ((foldRange) && foldRange->collapsed) {
sFold = mEdit->syntaxer()->foldString(sLine);
nFold = mEdit->stringWidth(sFold,mEdit->mDocument->lineWidth(vLine-1));
attr = mEdit->mSyntaxer->symbolAttribute();
getBraceColorAttr(mEdit->mSyntaxer->getState().braceLevel,attr);
addHighlightToken(
sFold, mEdit->mDocument->lineWidth(vLine-1)
, nFold, vLine, attr,false);
addOnStr = mEdit->syntaxer()->foldString(sLine);
} else {
// Draw LineBreak glyph.
if (mEdit->mOptions.testFlag(eoShowLineBreaks)
&& (!mIsLineSelected)
&& (!mIsSpecialLine)
&& (mEdit->mDocument->lineWidth(vLine-1) < mRight)) {
addHighlightToken(LineBreakGlyph,
mEdit->mDocument->lineWidth(vLine-1),
mEdit->mDocument->glyphWidth(LineBreakGlyph,0),vLine, mEdit->mSyntaxer->whitespaceAttribute(),false);
addOnStr = LineBreakGlyph;
}
}
if (!addOnStr.isEmpty()) {
expandGlyphStartCharList(addOnStr, sLine.length(), glyphStartCharList);
for (int i=0;i<glyphStartCharList.length()-glyphStartPositionsList.length();i++) {
glyphStartPositionsList.append(tokenLeft);
}
attr = mEdit->mSyntaxer->symbolAttribute();
getBraceColorAttr(mEdit->mSyntaxer->getState().braceLevel,attr);
int oldLen = sLine.length();
sLine += addOnStr;
addHighlightToken(
sLine,
addOnStr,
tokenLeft,
vLine, attr, false,
glyphStartCharList,
oldLen,
sLine.length(),
glyphStartPositionsList,
tokenWidth);
}
}
// Draw anything that's left in the TokenAccu record. Fill to the end
// of the invalid area with the correct colors.
paintHighlightToken(true);
paintHighlightToken(sLine, glyphStartCharList, glyphStartPositionsList, true);
//Paint editingAreaBorders
foreach (const PEditingArea& area, areaList) {

View File

@ -31,10 +31,14 @@ class QSynEditPainter
struct SynTokenAccu {
int width;
int left;
QString s;
int startGlyph;
int endGlyph;
// QString s;
QColor foreground;
QColor background;
FontStyles style;
QFont font;
QFont nonAsciiFont;
bool showSpecialGlyphs;
};
@ -54,13 +58,29 @@ private:
void computeSelectionInfo();
void setDrawingColors(bool selected);
int fixXValue(int xpos);
void paintToken(const QString& token, int tokenWidth, int tokenLeft,
void paintToken(
const QString& lineText,
const QList<int> &glyphStartCharList,
const QList<int> &glyphStartPositionList,
int startGlyph,
int endGlyph,
int tokenWidth, int tokenLeft,
int first, int last, bool isSelection, const QFont& font,
const QFont& fontForNonAscii, bool showGlyphs);
void paintEditAreas(const EditingAreaList& areaList);
void paintHighlightToken(bool bFillToEOL);
void addHighlightToken(const QString& token, int tokenLeft, int tokenWidth,
int line, PTokenAttribute p_Attri, bool showGlyphs);
void paintHighlightToken(const QString& lineText,
const QList<int> &glyphStartCharList,
const QList<int> &glyphStartPositionsList, bool bFillToEOL);
void addHighlightToken(
const QString& lineText,
const QString& token, int tokenLeft,
int line, PTokenAttribute p_Attri, bool showGlyphs,
const QList<int> glyphStartCharList,
int tokenStartChar,
int tokenEndChar,
QList<int> &glyphStartPositionList,
int &tokenWidth
);
void paintFoldAttributes();
void getBraceColorAttr(int level, PTokenAttribute &attr);

View File

@ -4288,29 +4288,29 @@
<context>
<name>QSynedit::Document</name>
<message>
<location filename="qsynedit/document.cpp" line="590"/>
<location filename="qsynedit/document.cpp" line="616"/>
<source>Can&apos;t open file &apos;%1&apos; for read!</source>
<translation>&quot;%1&quot;.</translation>
</message>
<message>
<location filename="qsynedit/document.cpp" line="630"/>
<location filename="qsynedit/document.cpp" line="753"/>
<location filename="qsynedit/document.cpp" line="656"/>
<location filename="qsynedit/document.cpp" line="779"/>
<source>Can&apos;t load codec &apos;%1&apos;!</source>
<translation>&quot;%1&quot;!</translation>
</message>
<message>
<location filename="qsynedit/document.cpp" line="649"/>
<location filename="qsynedit/document.cpp" line="675"/>
<source>&apos;%1&apos; is a binaray File!</source>
<oldsource>This is a binaray File!</oldsource>
<translation>&apos;%1&apos;</translation>
</message>
<message>
<location filename="qsynedit/document.cpp" line="756"/>
<location filename="qsynedit/document.cpp" line="782"/>
<source>Can&apos;t open file &apos;%1&apos; for save!</source>
<translation>&quot;%1&quot;!</translation>
</message>
<message>
<location filename="qsynedit/document.cpp" line="779"/>
<location filename="qsynedit/document.cpp" line="805"/>
<source>Data not correctly writed to file &apos;%1&apos;.</source>
<translation>&quot;%1&quot;</translation>
</message>
@ -4318,7 +4318,7 @@
<context>
<name>QSynedit::QSynEdit</name>
<message>
<location filename="qsynedit/painter.cpp" line="967"/>
<location filename="qsynedit/painter.cpp" line="1019"/>
<source>The syntaxer seems to be in an infinite loop</source>
<oldsource>The highlighter seems to be in an infinite loop</oldsource>
<translation></translation>