Skip to content

Commit

Permalink
skip over whitespaces first before finding the word start position to…
Browse files Browse the repository at this point in the history
… avoid breaking out of the spell check loop

closes #368
  • Loading branch information
stefankueng committed Mar 16, 2024
1 parent c0a1097 commit df980c1
Showing 1 changed file with 32 additions and 13 deletions.
45 changes: 32 additions & 13 deletions src/Commands/CmdSpellcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ void CCmdSpellCheck::Check()
#ifdef _DEBUG
ProfileTimer timer(L"SpellCheck");
#endif
// determine the spelling options for the current lexer and settings
bool checkAll = CIniSettings::Instance().GetInt64(L"spellcheck", L"checkall", 1) != 0;
bool checkUppercase = CIniSettings::Instance().GetInt64(L"spellcheck", L"uppercase", 1) != 0;
if (m_activeLexer != static_cast<int>(Scintilla().Lexer()))
Expand All @@ -183,39 +184,57 @@ void CCmdSpellCheck::Check()
Scintilla().SetWordChars(g_sentenceChars.c_str());
else
Scintilla().SetWordChars(g_wordChars.c_str());
// start at the first visible line and check all visible lines
Scintilla::TextRangeFull textRange{};
auto firstLine = Scintilla().FirstVisibleLine();
auto lastLine = firstLine + Scintilla().LinesOnScreen();
auto firstPos = static_cast<Sci_Position>(Scintilla().PositionFromLine(firstLine));
textRange.chrg.cpMin = firstPos;
textRange.chrg.cpMax = textRange.chrg.cpMin;
auto lastPos = Scintilla().PositionFromLine(lastLine) + Scintilla().LineLength(lastLine);
auto textLength = Scintilla().Length();
auto firstLine = Scintilla().FirstVisibleLine();
auto lastLine = firstLine + Scintilla().LinesOnScreen();
auto firstPos = static_cast<Sci_Position>(Scintilla().PositionFromLine(firstLine));
textRange.chrg.cpMin = firstPos;
textRange.chrg.cpMax = textRange.chrg.cpMin;
auto lastPos = Scintilla().PositionFromLine(lastLine) + Scintilla().LineLength(lastLine);
auto textLength = Scintilla().Length();
if (lastPos < 0)
lastPos = textLength - textRange.chrg.cpMin;
// if we already checked some text of the visible lines, start from there
if (m_lastCheckedPos)
textRange.chrg.cpMax = static_cast<Sci_Position>(m_lastCheckedPos);
auto start = GetTickCount64();
while (textRange.chrg.cpMax < lastPos)
{
if (GetTickCount64() - start > 100)
{
// to avoid a blocked UI, only check for 100ms and then continue later
m_lastCheckedPos = textRange.chrg.cpMax;
if (g_checkTimer)
SetTimer(GetHwnd(), g_checkTimer, 10, nullptr);
break;
}
// split the whole text either into words or if m_useComprehensiveCheck is true into sentences
Scintilla().SetWordChars(g_wordChars.c_str());
// skip over whitespace
while (textRange.chrg.cpMax < lastPos)
{
auto c = Scintilla().CharacterAt(textRange.chrg.cpMax);
if (c > 0x20)
break;
textRange.chrg.cpMax++;
}
// don't start in the middle of a word but at the beginning
textRange.chrg.cpMin = static_cast<Sci_Position>(Scintilla().WordStartPosition(textRange.chrg.cpMax + 1, TRUE));
if (m_useComprehensiveCheck)
Scintilla().SetWordChars(g_sentenceChars.c_str());
else
Scintilla().SetWordChars(g_wordChars.c_str());
if (textRange.chrg.cpMin < textRange.chrg.cpMax && textRange.chrg.cpMin >= firstPos)
{
DebugBreak();
break;
// word start is before the visible text, so we skip it
auto wordEnd = static_cast<Sci_Position>(Scintilla().WordEndPosition(textRange.chrg.cpMax, TRUE));
if (wordEnd <= textRange.chrg.cpMax)
{
DebugBreak();
break;
}
textRange.chrg.cpMax = wordEnd;
continue;
}
if (m_useComprehensiveCheck)
Scintilla().SetWordChars(g_sentenceChars.c_str());
textRange.chrg.cpMax = static_cast<Sci_Position>(Scintilla().WordEndPosition(textRange.chrg.cpMin, TRUE));
if (textRange.chrg.cpMax > lastPos)
{
Expand Down

0 comments on commit df980c1

Please sign in to comment.