work save

This commit is contained in:
Roy Qu 2024-02-23 21:43:58 +08:00
parent 3eadbafe25
commit 06b8850970
5 changed files with 149 additions and 112 deletions

View File

@ -46,6 +46,11 @@ Document::Document(const QFont& font, const QFont& nonAsciiFont, QObject *parent
mIndexOfLongestLine = -1;
mUpdateCount = 0;
mCharWidth = mFontMetrics.horizontalAdvance("M");
mUpdateDocumentLineWidthFunc = std::bind(&Document::calcLineWidth,
this,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3);
}
static void listIndexOutOfBounds(int index) {
@ -85,9 +90,6 @@ int Document::lineWidth(int line)
{
QMutexLocker locker(&mMutex);
if (line>=0 && line < mLines.size()) {
if (mLines[line]->width() == -1) {
return calculateLineWidth(line);
} else
return mLines[line]->width();
} else
return 0;
@ -100,9 +102,6 @@ int Document::lineWidth(int line, const QString &newText)
return 0;
QString lineText = mLines[line]->lineText();
if (lineText==newText) {
if (mLines[line]->width() == -1) {
return calculateLineWidth(line);
} else
return mLines[line]->width();
} else {
return stringWidth(newText,0);
@ -187,7 +186,8 @@ SyntaxState Document::getSyntaxState(int line)
void Document::insertItem(int line, const QString &s)
{
beginUpdate();
PDocumentLine documentLine = std::make_shared<DocumentLine>();
PDocumentLine documentLine = std::make_shared<DocumentLine>(
mUpdateDocumentLineWidthFunc);
documentLine->setLineText(s);
mIndexOfLongestLine = -1;
mLines.insert(line,documentLine);
@ -197,7 +197,7 @@ void Document::insertItem(int line, const QString &s)
void Document::addItem(const QString &s)
{
beginUpdate();
PDocumentLine line = std::make_shared<DocumentLine>();
PDocumentLine line = std::make_shared<DocumentLine>(mUpdateDocumentLineWidthFunc);
line->setLineText(s);
mIndexOfLongestLine = -1;
mLines.append(line);
@ -469,7 +469,6 @@ void Document::putLine(int index, const QString &s, bool notify) {
beginUpdate();
int oldColumns = mLines[index]->width();
mLines[index]->setLineText( s );
calculateLineWidth(index);
if (mIndexOfLongestLine == index && oldColumns>mLines[index]->width() )
mIndexOfLongestLine = -1;
else if (mIndexOfLongestLine>=0
@ -490,16 +489,6 @@ void Document::setUpdateState(bool Updating)
emit changed();
}
int Document::calculateLineWidth(int line)
{
PDocumentLine documentLine = mLines[line];
QList<int> glyphPositionList;
int width;
glyphPositionList = calcGlyphPositionList(documentLine->lineText(), documentLine->glyphStartCharList(), 0, width);
documentLine->setWidth(width, glyphPositionList);
return documentLine->width();
}
void Document::insertLines(int index, int numLines)
{
QMutexLocker locker(&mMutex);
@ -516,7 +505,7 @@ void Document::insertLines(int index, int numLines)
PDocumentLine line;
mLines.insert(index,numLines,line);
for (int i=index;i<index+numLines;i++) {
line = std::make_shared<DocumentLine>();
line = std::make_shared<DocumentLine>(mUpdateDocumentLineWidthFunc);
mLines[i]=line;
}
emit inserted(index,numLines);
@ -834,7 +823,7 @@ QString Document::glyphAt(int line, int charPos)
{
QMutexLocker locker(&mMutex);
QList<int> glyphStartCharList = mLines[line]->glyphStartCharList();
int glyphIdx = charToGlyphIndex(glyphStartCharList, charPos);
int glyphIdx = charToGlyphIndex(mLines[line]->lineText(), glyphStartCharList, charPos);
return mLines[line]->glyph(glyphIdx);
}
@ -842,7 +831,7 @@ int Document::charToGlyphStartChar(int line, int charPos)
{
QMutexLocker locker(&mMutex);
QList<int> glyphStartCharList = mLines[line]->glyphStartCharList();
int glyphIdx = charToGlyphIndex(glyphStartCharList, charPos);
int glyphIdx = charToGlyphIndex(mLines[line]->lineText(), glyphStartCharList, charPos);
return mLines[line]->glyphStartChar(glyphIdx);
}
@ -949,13 +938,17 @@ int Document::glyphWidth(const QString &glyph, int left) const
int Document::charToGlyphIndex(int line, int charIdx)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>count())
return 0;
QList<int> glyphStartCharList = mLines[line]->glyphStartCharList();
return charToGlyphIndex(glyphStartCharList, charIdx);
return charToGlyphIndex(mLines[line]->lineText(), glyphStartCharList, charIdx);
}
int Document::charToGlyphIndex(QList<int> glyphStartCharList, int charIdx) const
int Document::charToGlyphIndex(const QString& str, QList<int> glyphStartCharList, int charIdx) const
{
Q_ASSERT(charIdx>=0);
if (charIdx>=str.length())
return glyphStartCharList.length();
for (int i=0;i<glyphStartCharList.length();i++) {
if (glyphStartCharList[i]>charIdx) {
Q_ASSERT(i-1>=0);
@ -966,23 +959,29 @@ int Document::charToGlyphIndex(QList<int> glyphStartCharList, int charIdx) const
return glyphStartCharList.length()-1;
}
QList<int> Document::calcLineWidth(const QString &lineText, const QList<int> &glyphStartCharList, int &width)
{
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
}
int Document::xposToGlyphIndex(int line, int xpos)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return 0;
QList<int> glyphPositionList = mLines[line]->glyphPositionList();
return xposToGlyphIndex(glyphPositionList, xpos);
return xposToGlyphIndex(mLines[line]->width(), glyphPositionList, xpos);
}
int Document::xposToGlyphIndex(QList<int> glyphPositionList, int xpos) const
int Document::xposToGlyphIndex(int strWidth, QList<int> glyphPositionList, int xpos) const
{
Q_ASSERT(xpos>=0);
if (xpos>=strWidth)
return glyphPositionList.length();
for (int i=0;i<glyphPositionList.length();i++) {
if (glyphPositionList[i]>xpos) {
Q_ASSERT(i-1>=0);
return i-1;
}
}
Q_ASSERT(glyphPositionList.length()-1>=0);
return glyphPositionList.length()-1;
}
@ -990,15 +989,17 @@ int Document::charToGlyphStartPosition(int line, int charPos)
{
QMutexLocker locker(&mMutex);
QList<int> glyphStartCharList = mLines[line]->glyphStartCharList();
int glyphIdx = charToGlyphIndex(glyphStartCharList, charPos);
int glyphIdx = charToGlyphIndex(mLines[line]->lineText(), glyphStartCharList, charPos);
return mLines[line]->glyphStartPosition(glyphIdx);
}
int Document::xposToGlyphStartChar(int line, int xpos)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return 0;
QList<int> glyphPositionList = mLines[line]->glyphPositionList();
int glyphIdx = xposToGlyphIndex(glyphPositionList, xpos);
int glyphIdx = xposToGlyphIndex(mLines[line]->width(), glyphPositionList, xpos);
return mLines[line]->glyphStartChar(glyphIdx);
}
@ -1010,20 +1011,24 @@ int Document::charToGlyphStartPosition(int line, const QString newStr, int charP
glyphStartCharList = mLines[line]->glyphStartCharList();
else
glyphStartCharList = calcGlyphStartCharList(newStr);
int glyphIdx = charToGlyphIndex(glyphStartCharList, charPos);
int glyphIdx = charToGlyphIndex(mLines[line]->lineText(), glyphStartCharList, charPos);
return mLines[line]->glyphStartPosition(glyphIdx);
}
int Document::xposToGlyphStartChar(int line, const QString newStr, int xpos)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return 0;
QList<int> glyphPositionList;
if (mLines[line]->lineText() == newStr)
int width;
if (mLines[line]->lineText() == newStr) {
glyphPositionList = mLines[line]->glyphPositionList();
else {
glyphPositionList = calcGlyphPositionList(mLines[line]->lineText());
width = mLines[line]->width();
} else {
glyphPositionList = calcGlyphPositionList(mLines[line]->lineText(), width);
}
int glyphIdx = xposToGlyphIndex(glyphPositionList, xpos);
int glyphIdx = xposToGlyphIndex(width, glyphPositionList, xpos);
return mLines[line]->glyphStartChar(glyphIdx);
}
@ -1122,11 +1127,11 @@ QList<int> Document::calcGlyphPositionList(const QString &lineText, const QList<
return glyphPostionList;
}
QList<int> Document::calcGlyphPositionList(const QString &lineText) const
QList<int> Document::calcGlyphPositionList(const QString &lineText, int &width) const
{
QList<int> glyphStartCharList = calcGlyphStartCharList(lineText);
int right;
return calcGlyphPositionList(lineText,glyphStartCharList,0,right);
return calcGlyphPositionList(lineText,glyphStartCharList,0,width);
}
NewlineType Document::getNewlineType()
@ -1156,15 +1161,17 @@ void Document::invalidateAllLineWidth()
}
}
DocumentLine::DocumentLine():
DocumentLine::DocumentLine(DocumentLine::UpdateWidthFunc updateWidthFunc):
mSyntaxState{},
mWidth{-1}
mWidth{-1},
mUpdateWidthFunc{updateWidthFunc}
{
}
int DocumentLine::glyphLength(int i) const
{
Q_ASSERT(i>=0 && i<mGlyphStartCharList.length());
if (i<0 || i>=mGlyphStartCharList.length())
return 0;
int start = glyphStartChar(i);
int end;
if (i+1<mGlyphStartCharList.length()) {
@ -1175,20 +1182,47 @@ int DocumentLine::glyphLength(int i) const
return end-start;
}
int DocumentLine::glyphWidth(int i) const
QString DocumentLine::glyph(int i) const
{
Q_ASSERT(mWidth>=0);
Q_ASSERT(i>=0 && i<mGlyphPositionList.length());
if (i<0 || i>=mGlyphStartCharList.length())
return QString();
return mLineText.mid(glyphStartChar(i),glyphLength(i));
}
int DocumentLine::glyphStartPosition(int i)
{
if (i<0)
return 0;
if (mWidth<0)
updateWidth();
if (i>=mGlyphPositionList.length())
return mWidth;
return mGlyphPositionList[i];
}
int DocumentLine::glyphWidth(int i)
{
if (i<0 || i>=mGlyphPositionList.length())
return 0;
if(mWidth<0)
updateWidth();
int start = glyphStartPosition(i);
int end;
if (i+1<mGlyphPositionList.length()) {
end = mGlyphPositionList[i+1];
} else {
end = mWidth+1;
end = mWidth;
}
return end-start;
}
int DocumentLine::width()
{
if(mWidth<0)
updateWidth();
return mWidth;
}
void DocumentLine::setLineText(const QString &newLineText)
{
mLineText = newLineText;
@ -1196,6 +1230,29 @@ void DocumentLine::setLineText(const QString &newLineText)
mGlyphStartCharList = calcGlyphStartCharList(newLineText);
}
void DocumentLine::updateWidth()
{
Q_ASSERT(mUpdateWidthFunc!=nullptr);
mGlyphPositionList = mUpdateWidthFunc(mLineText, mGlyphStartCharList, mWidth);
qDebug()<<mLineText<<mWidth<<mGlyphPositionList;
}
const QList<int> &DocumentLine::glyphPositionList()
{
if(mWidth<0)
updateWidth();
return mGlyphPositionList;
}
int DocumentLine::glyphStartChar(int i) const
{
if (i<0)
return 0;
if (i>=mGlyphStartCharList.length())
return mLineText.length();
return mGlyphStartCharList[i];
}
UndoList::UndoList():QObject()
{
mMaxUndoActions = 1024;

View File

@ -34,6 +34,7 @@ QList<int> calcGlyphStartCharList(const QString &text);
class Document;
using SearchConfirmAroundProc = std::function<bool ()>;
/**
* @brief The DocumentLine class
*
@ -50,7 +51,9 @@ class Document;
*/
class DocumentLine {
public:
explicit DocumentLine();
using UpdateWidthFunc = std::function<QList<int>(const QString&, const QList<int> &, int &)>;
explicit DocumentLine(UpdateWidthFunc updateWidthFunc);
DocumentLine(const DocumentLine&)=delete;
DocumentLine& operator=(const DocumentLine&)=delete;
@ -78,22 +81,14 @@ 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 {
Q_ASSERT(mWidth>=0);
return mGlyphPositionList;
}
const QList<int>& glyphPositionList();
/**
* @brief get start index of the chars representing the specified glyph.
* @param i index of the glyph in the line (starting from 0)
* @return char index in the line text (start from 0)
*/
int glyphStartChar(int i) const {
Q_ASSERT(i>=0);
if (i>=mGlyphStartCharList.length())
return mLineText.length();
return mGlyphStartCharList[i];
}
int glyphStartChar(int i) const;
/**
* @brief get count of the chars representing the specified glyph.
@ -107,29 +102,21 @@ private:
* @param i index of the glyph in the line (starting from 0)
* @return the chars representing the specified glyph
*/
QString glyph(int i) const {
return mLineText.mid(glyphStartChar(i),glyphLength(i));
}
QString glyph(int i) const;
/**
* @brief get start position of the specified glyph.
* @param i index of the glyph in the line (starting from 0)
* @return start position in the line (pixel)
*/
int glyphStartPosition(int i) const {
Q_ASSERT(mWidth>=0);
Q_ASSERT(i>=0);
if (i>mGlyphPositionList.length())
return mWidth+1;
return mGlyphPositionList[i];
}
int glyphStartPosition(int i);
/**
* @brief get width pixels) of the specified glyph.
* @param i index of the glyph of the line (starting from 0)
* @return
*/
int glyphWidth(int i) const;
int glyphWidth(int i);
/**
* @brief get the line text
@ -141,7 +128,7 @@ private:
* @brief get the width (pixel) of the line text
* @return the width (in width)
*/
int width() const { return mWidth; }
int width();
/**
* @brief get the state of the syntax highlighter after this line is parsed
@ -155,7 +142,7 @@ private:
void setSyntaxState(const SyntaxState &newSyntaxState) { mSyntaxState = newSyntaxState; }
void setLineText(const QString &newLineText);
void setWidth(int width, QList<int> glyphPositionList) { mWidth = width; mGlyphPositionList = glyphPositionList; }
void updateWidth();
void invalidateWidth() { mWidth = -1; mGlyphPositionList.clear(); }
private:
QString mLineText; /* the unicode code points of the text */
@ -191,6 +178,8 @@ private:
*/
int mWidth;
UpdateWidthFunc mUpdateWidthFunc;
friend class Document;
};
@ -506,7 +495,6 @@ public:
* @return glyph index in the line (starting from 0)
*/
int charToGlyphIndex(int line, int charPos);
int charToGlyphIndex(QList<int> glyphStartCharList, int charPos) const;
/**
* @brief get index of the glyph displayed on the specified column
@ -518,7 +506,6 @@ public:
* @return glyph index in the line (starting from 0)
*/
int xposToGlyphIndex(int line, int xpos);
int xposToGlyphIndex(QList<int> glyphColumnsList, int xpos) const;
int charToGlyphStartPosition(int line, int charPos);
int xposToGlyphStartChar(int line, int xpos);
@ -564,9 +551,11 @@ protected:
void putTextStr(const QString& text);
void internalClear();
private:
int calculateLineWidth(int line);
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, int left, int &right) const;
QList<int> calcGlyphPositionList(const QString& lineText) const;
QList<int> calcGlyphPositionList(const QString& lineText, int &width) const;
bool tryLoadFileByEncoding(QByteArray encodingName, QFile& file);
void loadUTF16BOMFile(QFile& file);
void loadUTF32BOMFile(QFile& file);
@ -576,6 +565,8 @@ private:
private:
DocumentLines mLines;
DocumentLine::UpdateWidthFunc mUpdateDocumentLineWidthFunc;
//SynEdit* mEdit;
QFontMetrics mFontMetrics;

View File

@ -361,8 +361,9 @@ void QSynEditPainter::paintToken(
bool startPaint;
int nX;
// qDebug()<<"Paint token"<<token<<tokenWidth<<tokenLeft<<first<<last<<rcToken;
if (last >= first && rcToken.right() > rcToken.left()) {
// qDebug()<<"Paint Token"<<Token<<ColumnsBefore<<TokenCols<<First<<Last;
nX = fixXValue(first);
first -= tokenLeft;
last -= tokenLeft;
@ -429,6 +430,7 @@ void QSynEditPainter::paintToken(
ch=glyph;
}
mPainter->drawText(nX+padding,rcToken.bottom()-mPainter->fontMetrics().descent() , ch);
//qDebug()<<"Drawing"<<glyph<<nX<<glyphWidth;
} else {
mPainter->setFont(fontForNonAscii);
mPainter->drawText(nX,rcToken.bottom()-mPainter->fontMetrics().descent() , glyph);
@ -443,7 +445,7 @@ void QSynEditPainter::paintToken(
}
}
rcToken.setLeft(rcToken.right());
rcToken.setLeft(rcToken.right()+1);
}
}
@ -1038,23 +1040,6 @@ void QSynEditPainter::paintLines()
// Let the highlighter scan the next token.
mEdit->mSyntaxer->next();
}
// // Don't assume HL.GetTokenPos is valid after HL.GetEOL == True.
// //nTokenColumnsBefore += edit->stringColumns(sToken,nTokenColumnsBefore);
// if (edit->mSyntaxer->eol() && (nTokenColumnsBefore < vLastChar)) {
// int lineColumns = edit->mDocument->lineColumns(vLine-1);
// // Draw text that couldn't be parsed by the highlighter, if any.
// if (nTokenColumnsBefore < lineColumns) {
// if (nTokenColumnsBefore + 1 < vFirstChar)
// nTokenColumnsBefore = vFirstChar - 1;
// nTokenColumnLen = std::min(lineColumns, vLastChar) - (nTokenColumnsBefore + 1);
// if (nTokenColumnLen > 0) {
// sToken = edit->substringByColumns(sLine,nTokenColumnsBefore+1,nTokenColumnLen);
// addHighlightToken(sToken, nTokenColumnsBefore - (vFirstChar - FirstCol),
// nTokenColumnLen, vLine, PTokenAttribute(),false);
// }
// }
// }
// Paint folding
foldRange = mEdit->foldStartAtLine(vLine);
if ((foldRange) && foldRange->collapsed) {

View File

@ -722,10 +722,14 @@ DisplayCoord QSynEdit::pixelsToNearestGlyphPos(int aX, int aY) const
int xpos = std::max(0, leftPos() + aX - mGutterWidth - 2);
int row = yposToRow(aY);
int line = rowToLine(row);
if (line<1 || line > mDocument->count() )
return DisplayCoord{-1,-1};
if (xpos<0 || xpos>mDocument->lineWidth(line-1))
return DisplayCoord{-1,-1};
if (line<1)
line = 1;
if (line>mDocument->count())
line = mDocument->count();
if (xpos<0)
xpos=0;
if (xpos>mDocument->lineWidth(line-1))
xpos=mDocument->lineWidth(line-1)+1;
int glyphIndex = mDocument->xposToGlyphIndex(line-1, xpos);
xpos = mDocument->glyphStartPostion(line-1, glyphIndex);
return DisplayCoord{xpos, row};

View File

@ -124,9 +124,9 @@ enum class TransientType {
using SynPaintTransientProc = std::function<void(const QPaintDevice& paintDevice,
SynTransientType transientType)>;
*/
using ProcessCommandProc = std::function<void(EditCommand& command, QChar& AChar, void* data)>;
using MouseCursorProc = std::function<void(const BufferCoord& aLineCharPos, QCursor & aCursor)>;
using PaintProc = std::function<void(const QPaintDevice& paintDevice )>;
// using ProcessCommandProc = std::function<void(EditCommand& command, QChar& AChar, void* data)>;
// using MouseCursorProc = std::function<void(const BufferCoord& aLineCharPos, QCursor & aCursor)>;
// using PaintProc = std::function<void(const QPaintDevice& paintDevice )>;
using SearchMathedProc = std::function<SearchAction(const QString& sSearch,
const QString& sReplace, int Line, int ch, int wordLen)>;
using SearchConfirmAroundProc = std::function<bool ()>;
@ -737,12 +737,12 @@ private:
int mPainterLock; // lock counter to prevent repaint while painting
bool mUndoing;
// event handlers
ProcessCommandProc mOnCommandProcessed;
MouseCursorProc mOnMouseCursor;
PaintProc mOnPaint;
// ProcessCommandProc mOnCommandProcessed;
// MouseCursorProc mOnMouseCursor;
// PaintProc mOnPaint;
// SynPreparePaintHighlightTokenProc mOnPaintHighlightToken;
ProcessCommandProc mOnProcessingCommand;
ProcessCommandProc mOnProcessingUserCommand;
// ProcessCommandProc mOnProcessingCommand;
// ProcessCommandProc mOnProcessingUserCommand;
// SynSpecialLineColorsProc mOnSpecialLineColors;
// SynEditingAreasProc mOnEditingAreas;