Skip to content

Commit

Permalink
Implement wxTextCtrl::SearchText() for wxGTK3
Browse files Browse the repository at this point in the history
  • Loading branch information
Blake-Madden authored and vadz committed Jan 8, 2025
1 parent e314f2c commit d8ba9ce
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 3 deletions.
4 changes: 4 additions & 0 deletions include/wx/gtk/textctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ class WXDLLIMPEXP_CORE wxTextCtrl: public wxTextCtrlBase
virtual wxTextProofOptions GetProofCheckOptions() const override;
#endif // wxUSE_SPELLCHECK && __WXGTK3__

#ifdef __WXGTK3__
virtual wxTextSearchResult SearchText(const wxTextSearch& search) const override;
#endif // __WXGTK3__

// GTK-specific functions

// Get the underlying text buffer for multi-line controls.
Expand Down
4 changes: 2 additions & 2 deletions interface/wx/textctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1813,11 +1813,11 @@ class wxTextCtrl : public wxControl,
The range of the match will be returned as a wxTextSearchResult, which will
contain -1 values if no match was found.
This is currently only implemented under wxMSW.
This is currently only implemented under wxMSW and wxGTK3.
@since 3.3.0
@onlyfor{wxmsw}
@onlyfor{wxmsw,wxgtk}
*/
wxTextSearchResult SearchText(const wxTextSearch& search) const;

Expand Down
72 changes: 72 additions & 0 deletions src/gtk/textctrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2074,6 +2074,78 @@ bool wxTextCtrl::GetStyle(long position, wxTextAttr& style)
return true;
}

#ifdef __WXGTK3__

wxTextSearchResult wxTextCtrl::SearchText(const wxTextSearch& search) const
{
if ( !IsMultiLine() )
{
return wxTextSearchResult{};
}

int flags = GTK_TEXT_SEARCH_TEXT_ONLY;
if ( !search.m_matchCase )
flags |= GTK_TEXT_SEARCH_CASE_INSENSITIVE;

// get the beginning and end of text buffer
GtkTextIter textStart, textEnd;
gtk_text_buffer_get_start_iter(m_buffer, &textStart);
gtk_text_buffer_get_end_iter(m_buffer, &textEnd);

const bool forward = search.m_direction == wxTextSearch::Direction::Down;

// start search at the start or at the end depending on the direction
GtkTextIter searchStart = forward ? textStart : textEnd;

// but user-provided position overrides the default starting position
if ( search.m_startingPosition != -1 )
{
gtk_text_buffer_get_iter_at_offset(m_buffer, &searchStart,
static_cast<gint>(search.m_startingPosition));
}

// the match results
GtkTextIter selectionStart, selectionEnd;

const auto searchFunc = forward ? gtk_text_iter_forward_search
: gtk_text_iter_backward_search;
for ( ;; )
{
if ( !searchFunc
(
&searchStart,
search.m_searchValue.utf8_str(),
static_cast<GtkTextSearchFlags>(flags),
&selectionStart,
&selectionEnd,
nullptr // no limit
) )
{
// If we haven't found anything at all, we're done.
return wxTextSearchResult{};
}

// But if we did find something, we may need to check whether it was
// a whole word.
if ( !search.m_wholeWord )
break;

// Check if this is a whole-word match.
if ( gtk_text_iter_starts_word(&selectionStart) &&
gtk_text_iter_ends_word(&selectionEnd) )
break;

// Not a whole-word match, keep searching for the next match, maybe it
// will be a whole-word one.
searchStart = selectionEnd;
}

return wxTextSearchResult{ gtk_text_iter_get_offset(&selectionStart),
gtk_text_iter_get_offset(&selectionEnd) };
}

#endif // __WXGTK3__

void wxTextCtrl::DoApplyWidgetStyle(GtkRcStyle *style)
{
GTKApplyStyle(m_text, style);
Expand Down
6 changes: 5 additions & 1 deletion tests/controls/textctrltest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1487,7 +1487,7 @@ TEST_CASE("wxTextCtrl::Get/SetRTFValue", "[wxTextCtrl][rtf]")
}
#endif

#ifdef __WXMSW__
#if defined(__WXMSW__) || defined(__WXGTK3__)
TEST_CASE("wxTextCtrl::SearchText", "[wxTextCtrl][search]")
{
wxWindow* const parent = wxTheApp->GetTopWindow();
Expand Down Expand Up @@ -1557,6 +1557,10 @@ And there is a mispeled word)");
results = text->SearchText(wxTextSearch(L"very").SearchDirection(wxTextSearch::Direction::Down).MatchCase().MatchWholeWord().Start(results.m_start + 1));
CHECK_FALSE(results);

// bad start position
results = text->SearchText(wxTextSearch(L"very").SearchDirection(wxTextSearch::Direction::Down).MatchCase().MatchWholeWord().Start(2000));
CHECK_FALSE(results); // started past the length of the control

// go up from the end
results = text->SearchText(wxTextSearch(L"very").SearchDirection(wxTextSearch::Direction::Up).MatchCase().MatchWholeWord());
CHECK(results);
Expand Down

0 comments on commit d8ba9ce

Please sign in to comment.