input method processing for line has selections and special areas

- fix: add mutex lock to prevent rare conditions when editor is modifying and the content is read
This commit is contained in:
royqh1979@gmail.com 2021-10-05 21:25:23 +08:00
parent f8f5b7b0d8
commit ffb87fe66c
7 changed files with 97 additions and 20 deletions

View File

@ -1181,8 +1181,10 @@ void Editor::addSyntaxIssues(int line, int startChar, int endChar, CompileIssueT
}
pError->startChar = start;
pError->endChar = start + token.length();
pError->col = charToColumn(line,pError->startChar);
pError->endCol = charToColumn(line,pError->endChar);
// pError->col = charToColumn(line,pError->startChar);
// pError->endCol = charToColumn(line,pError->endChar);
pError->col = pError->startChar;
pError->endCol = pError->endChar;
pError->hint = hint;
pError->token = token;
pError->issueType = errorType;

View File

@ -297,7 +297,7 @@ bool EditorList::getContentFromOpenedEditor(const QString &filename, QStringList
Editor * e= getOpenedEditorByFilename(filename);
if (!e)
return false;
buffer = e->lines()->contents();
buffer = e->contents();
return true;
}

View File

@ -4070,7 +4070,7 @@ void MainWindow::on_btnReplace_clicked()
tr("Can't open file '%1' for replace!").arg(file->filename));
return;
}
contents = editor->lines()->contents();
contents = editor->contents();
for (int i=file->results.count()-1;i>=0;i--) {
const PSearchResultTreeItem& item = file->results[i];
QString line = contents[item->line-1];

View File

@ -532,6 +532,12 @@ BufferCoord SynEdit::getMatchingBracketEx(BufferCoord APoint)
return BufferCoord{0,0};
}
QStringList SynEdit::contents()
{
QMutexLocker locker(&mMutex);
return lines()->contents();
}
bool SynEdit::getPositionOfMouse(BufferCoord &aPos)
{
QPoint point = QCursor::pos();
@ -891,7 +897,8 @@ void SynEdit::invalidateLine(int Line)
QRect rcInval;
if (mPainterLock >0)
return;
if (Line<1 || Line>mLines->count() || !isVisible())
if (Line<1 || (Line>mLines->count() &&
Line!=1) || !isVisible())
return;
// invalidate text area of this line
@ -4325,6 +4332,7 @@ void SynEdit::setSelTextPrimitiveEx(SynSelectionMode PasteMode, const QString &V
void SynEdit::setSelText(const QString &Value)
{
QMutexLocker locker(&mMutex);
mUndoList->BeginBlock();
auto action = finally([this]{
mUndoList->EndBlock();
@ -4865,6 +4873,7 @@ void SynEdit::onCommandProcessed(SynEditorCommand , QChar , void *)
void SynEdit::ExecuteCommand(SynEditorCommand Command, QChar AChar, void *pData)
{
QMutexLocker locker(&mMutex);
incPaintLock();
auto action=finally([this] {
decPaintLock();
@ -5597,9 +5606,8 @@ void SynEdit::mouseDoubleClickEvent(QMouseEvent *event)
void SynEdit::inputMethodEvent(QInputMethodEvent *event)
{
qDebug()<<"---";
qDebug()<<event->replacementStart()<<":"<<event->replacementLength()<<" - "
<< event->preeditString()<<" - "<<event->commitString();
// qDebug()<<event->replacementStart()<<":"<<event->replacementLength()<<" - "
// << event->preeditString()<<" - "<<event->commitString();
QString oldString = mInputPreeditString;
mInputPreeditString = event->preeditString();

View File

@ -5,6 +5,7 @@
#include <QCursor>
#include <QDateTime>
#include <QFrame>
#include <QMutex>
#include <QStringList>
#include <QTimer>
#include <QWidget>
@ -256,6 +257,8 @@ public:
virtual BufferCoord getMatchingBracket();
virtual BufferCoord getMatchingBracketEx(BufferCoord APoint);
QStringList contents();
bool getPositionOfMouse(BufferCoord& aPos);
bool getLineOfMouse(int& line);
bool pointToCharLine(const QPoint& point, BufferCoord& coord);
@ -672,6 +675,8 @@ private:
QString mInputPreeditString;
QRecursiveMutex mMutex;
friend class SynEditTextPainter;
// QWidget interface

View File

@ -230,7 +230,8 @@ void SynEditStringList::setContents(const QStringList &text)
QStringList SynEditStringList::contents()
{
QStringList Result;
foreach (const PSynEditStringRec& line, mList) {
SynEditStringRecList list = mList;
foreach (const PSynEditStringRec& line, list) {
Result.append(line->fString);
}
return Result;

View File

@ -301,6 +301,14 @@ void SynEditTextPainter::ComputeSelectionInfo()
}
} else
bAnySelection = false;
if (edit->mInputPreeditString.length()>0) {
if (vStart.Line == edit->mCaretY && vStart.Char >=edit->mCaretX) {
vStart.Char+=edit->mInputPreeditString.length();
}
if (vEnd.Line == edit->mCaretY && vEnd.Char >edit->mCaretX) {
vEnd.Char+=edit->mInputPreeditString.length();
}
}
// If there is any visible selection so far, then test if there is an
// intersection with the area to be painted.
if (bAnySelection) {
@ -310,6 +318,20 @@ void SynEditTextPainter::ComputeSelectionInfo()
// Transform the selection from text space into screen space
vSelStart = edit->bufferToDisplayPos(vStart);
vSelEnd = edit->bufferToDisplayPos(vEnd);
if (edit->mInputPreeditString.length()
&& vStart.Line == edit->mCaretY) {
QString sLine = edit->lineText().left(edit->mCaretX-1)
+ edit->mInputPreeditString
+ edit->lineText().mid(edit->mCaretX-1);
vSelStart.Column = edit->charToColumn(sLine,vStart.Char);
}
if (edit->mInputPreeditString.length()
&& vEnd.Line == edit->mCaretY) {
QString sLine = edit->lineText().left(edit->mCaretX-1)
+ edit->mInputPreeditString
+ edit->lineText().mid(edit->mCaretX-1);
vSelEnd.Column = edit->charToColumn(sLine,vEnd.Char);
}
// In the column selection mode sort the begin and end of the selection,
// this makes the painting code simpler.
if (edit->mActiveSelectionMode == SynSelectionMode::smColumn && vSelStart.Column > vSelEnd.Column)
@ -365,6 +387,8 @@ void SynEditTextPainter::PaintToken(const QString &Token, int TokenCols, int Col
}
startPaint = true;
}
if (tokenColLen+charCols > Last)
break;
//painter->drawText(nX,rcToken.bottom()-painter->fontMetrics().descent()*edit->dpiFactor() , Token[i]);
if (startPaint) {
painter->drawText(nX,rcToken.bottom()-painter->fontMetrics().descent() , Token[i]);
@ -372,8 +396,6 @@ void SynEditTextPainter::PaintToken(const QString &Token, int TokenCols, int Col
}
tokenColLen += charCols;
if (tokenColLen > Last)
break;
}
}
@ -712,6 +734,7 @@ void SynEditTextPainter::PaintLines()
int vLastChar;
SynEditingAreaList areaList;
PSynEditFoldRange foldRange;
PSynHighlighterAttribute preeditAttr;
int nFold;
QString sFold;
@ -806,6 +829,10 @@ void SynEditTextPainter::PaintLines()
nTokenColumnLen += edit->charColumns(SynLineBreakGlyph);
}
if (bComplexLine) {
setDrawingColors(true);
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelStart)));
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelEnd)));
PaintToken(sToken, nTokenColumnLen, 0, nLineSelStart, nLineSelEnd,false);
setDrawingColors(false);
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(FirstCol)));
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelStart)));
@ -813,14 +840,20 @@ void SynEditTextPainter::PaintLines()
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelEnd)));
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(LastCol)));
PaintToken(sToken, nTokenColumnLen, 0, nLineSelEnd, LastCol,true);
setDrawingColors(true);
rcToken.setLeft(std::max(rcLine.left(), ColumnToXValue(nLineSelStart)));
rcToken.setRight(std::min(rcLine.right(), ColumnToXValue(nLineSelEnd)));
PaintToken(sToken, nTokenColumnLen, 0, nLineSelStart, nLineSelEnd - 1,false);
} else {
setDrawingColors(bLineSelected);
PaintToken(sToken, nTokenColumnLen, 0, FirstCol, LastCol,bLineSelected);
}
//Paint editingAreaBorders
if (bCurrentLine && edit->mInputPreeditString.length()>0) {
PSynEditingArea area = std::make_shared<SynEditingArea>();
area->beginX = edit->charToColumn(sLine,edit->mCaretX);
area->endX = edit->charToColumn(sLine,edit->mCaretX + edit->mInputPreeditString.length());
area->type = SynEditingAreaType::eatUnderLine;
area->color = colFG;
areaList.append(area);
PaintEditAreas(areaList);
}
} else {
// Initialize highlighter with line text and range info. It is
// necessary because we probably did not scan to the end of the last
@ -876,6 +909,19 @@ void SynEditTextPainter::PaintLines()
} else if (sToken == "}") {
GetBraceColorAttr(edit->mHighlighter->getRangeState().braceLevel+1,attr);
}
if (bCurrentLine && edit->mInputPreeditString.length()>0) {
int startPos = edit->mHighlighter->getTokenPos()+1;
int endPos = edit->mHighlighter->getTokenPos() + sToken.length();
qDebug()<<startPos<<":"<<endPos<<" - "+sToken+" - "<<edit->mCaretX<<":"<<edit->mCaretX+edit->mInputPreeditString.length();
if (!(endPos < edit->mCaretX
|| startPos >= edit->mCaretX+edit->mInputPreeditString.length())) {
if (!preeditAttr) {
preeditAttr = attr;
} else {
attr = preeditAttr;
}
}
}
AddHighlightToken(sToken, nTokenColumnsBefore - (vFirstChar - FirstCol),
nTokenColumnLen, vLine,attr);
}
@ -921,13 +967,30 @@ void SynEditTextPainter::PaintLines()
// of the invalid area with the correct colors.
PaintHighlightToken(true);
//Paint editingAreaBorders
foreach (const PSynEditingArea& area, areaList) {
if (bCurrentLine && edit->mInputPreeditString.length()>0) {
if (area->beginX >= edit->mCaretX) {
area->beginX+=edit->mInputPreeditString.length();
}
if (area->endX > edit->mCaretX) {
area->endX+=edit->mInputPreeditString.length();
}
}
area->beginX = edit->charToColumn(sLine, area->beginX);
area->endX = edit->charToColumn(sLine,area->endX);
}
if (bCurrentLine && edit->mInputPreeditString.length()>0) {
PSynEditingArea area = std::make_shared<SynEditingArea>();
area->beginX = edit->mCaretX;
area->endX = edit->mCaretX + edit->mInputPreeditString.length();
area->beginX = edit->charToColumn(sLine, edit->mCaretX);
area->endX = edit->charToColumn(sLine, edit->mCaretX + edit->mInputPreeditString.length());
area->type = SynEditingAreaType::eatUnderLine;
area->color = colFG;
if (preeditAttr) {
area->color = preeditAttr->foreground();
} else {
area->color = colFG;
}
areaList.append(area);
}
PaintEditAreas(areaList);
@ -948,5 +1011,3 @@ void SynEditTextPainter::drawMark(PSynEditMark , int &, int )
{
//todo
}