Spell checking wxStyledTextCtrl

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Moonslate
Earned a small fee
Earned a small fee
Posts: 10
Joined: Sat Aug 24, 2019 10:09 am

Spell checking wxStyledTextCtrl

Post by Moonslate » Sun Dec 01, 2019 9:54 pm

I'm wanting to use a spell checker for wxStyledTextCtrl. It's needs to wait the user to end typing, end then check the text typed. It looks like DSpellCheck for Notepad++. This is how I'm trying:

Code: Select all

const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
in the char added event:

Code: Select all

m_lastTyped = (std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() * 0.001);

	size_t curPos = m_stc->GetCurrentPos();
	
	if (m_endTyping)
	{
		m_typedMinPos = curPos;
		m_typedMaxPos = curPos;
	}

	m_endTyping = false;

	if (m_typedMinPos > curPos)
		m_typedMinPos = curPos;

	if (m_typedMaxPos < curPos)
		m_typedMaxPos = curPos;

	CallAfter(&cScriptEditor::UpdateStatusText, m_stc);

	event.Skip();
and in the on style needed:

Code: Select all

	//from here
	int line = m_stc->GetCurrentLine();
	int start = m_stc->PositionFromLine(line);
	int end = m_stc->GetLineEndPosition(line);

	m_stc->StartStyling(start);
	m_stc->SetStyling(m_stc->LineLength(line), 0); //Clear old style

	FindAndHighlightAllVars(m_stc, start, end);

	VerifyCurLineLenght(m_stc);
	//to here is just styling. The next code is for the spell	
	
	double now = (std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()).time_since_epoch().count() * 0.001);

	double elapsed = now - m_lastTyped;

	if (elapsed > 500 && !m_endTyping)
	{
		m_endTyping = true;	

		DoSpelling(m_stc, m_stc->WordStartPosition(m_typedMinPos, false), m_stc->WordEndPosition(m_typedMaxPos, false));
	}
	event.Skip();
The DoSpelling function:

Code: Select all

	std::string s = stc->GetTextRange(start, end).ToStdString();

	size_t npos = std::string::npos;

	m_stc->IndicatorClearRange(start, end - start);

	for (size_t first = s.find_first_of(letters, 0); first != npos; first = s.find_first_of(letters, first))
	{
		size_t last = s.find_first_not_of(letters, first);

		std::string word = s.substr(first, last != npos ? last - first : s.size() - first);

		bool isGood = m_hunspell->spell(s);

		if (!isGood)
			m_stc->IndicatorFillRange(start + first, last != npos ? last - first : s.size() - first);

		first = last;
	}
This works, but, i'm clearing the old style, so, the OnStyleNeeded is not called any more when the users stops to type. When the user delete a char, the OnStyleNeeded is called again and (elapsed > 500) returns true. I tried using another thread with a while(true) to call DoSpelling, but, sometimes, when I close the frame, the another thread still trying to spell the StyledTextCtrl, and the program crash. I tried to compile wxSpellChecker, but I got erros. I think because is too old, well, I really need to use spell checking in my application. Any idea?

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 4365
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Spell checking wxStyledTextCtrl

Post by ONEEYEMAN » Mon Dec 02, 2019 4:38 am

Hi,
Do you really need wxSTC?
Maybe wxTextCtrl or wxRTC will suffice?

Thank you.

User avatar
evstevemd
Part Of The Furniture
Part Of The Furniture
Posts: 2293
Joined: Wed Jan 28, 2009 11:57 am
Location: United Republic of Tanzania
Contact:

Re: Spell checking wxStyledTextCtrl

Post by evstevemd » Tue Dec 03, 2019 12:10 pm

I have done spellcheck with wxSTC before. I used hunspell to do the checking. For showing spell errors wxSTC have indicators (like squiggled line). With some effort you can use Dwell start event to show error message when hovered or trigger autocompshow with suggestions.

For showing it when user finishes typing you will need to debounce the text change event of your choice. wx does not support that out of the box but check this thread for ideas
Chief Justice: We have trouble dear citizens!
Citizens: What it is his honor?
Chief Justice:Our president is an atheist, who will he swear to?
[Ubuntu 19.04/Windows 10 Pro/MacOS 10.13 - GCC/MinGW/Clang, CodeLite IDE]

Post Reply