From 472aec2d7e53c68274c9f11fd608f22895adc3d1 Mon Sep 17 00:00:00 2001 From: iwbnwif Date: Wed, 18 Aug 2021 21:17:04 +0100 Subject: [PATCH] Add support for using native spell checking in wxTextCtrl Add wxTextCtrl::EnableSpellCheck() and implement it for wxMSW and wxGTK3. Closes #17544. --- build/cmake/setup.h.in | 6 ++ build/tools/before_install.sh | 2 +- configure | 149 ++++++++++++++++++++++++++++++++++ configure.in | 43 ++++++++++ include/wx/android/setup.h | 12 +++ include/wx/gtk/setup.h | 12 +++ include/wx/gtk/textctrl.h | 8 ++ include/wx/motif/setup.h | 12 +++ include/wx/msw/setup.h | 12 +++ include/wx/msw/textctrl.h | 9 ++ include/wx/osx/setup.h | 12 +++ include/wx/setup_inc.h | 12 +++ include/wx/textctrl.h | 48 +++++++++++ include/wx/univ/setup.h | 12 +++ interface/wx/textctrl.h | 97 +++++++++++++++++++++- samples/text/text.cpp | 15 +++- setup.h.in | 6 ++ src/gtk/textctrl.cpp | 57 +++++++++++++ src/msw/textctrl.cpp | 55 ++++++++++++- 19 files changed, 575 insertions(+), 4 deletions(-) diff --git a/build/cmake/setup.h.in b/build/cmake/setup.h.in index d052b2f03c..29fae22477 100644 --- a/build/cmake/setup.h.in +++ b/build/cmake/setup.h.in @@ -216,6 +216,12 @@ #cmakedefine01 wxUSE_SECRETSTORE +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#cmakedefine01 wxUSE_SPELLCHECK +#else +#cmakedefine01 wxUSE_SPELLCHECK +#endif + #cmakedefine01 wxUSE_STDPATHS #cmakedefine01 wxUSE_TEXTBUFFER diff --git a/build/tools/before_install.sh b/build/tools/before_install.sh index 87b1fb0c94..373020c2e3 100755 --- a/build/tools/before_install.sh +++ b/build/tools/before_install.sh @@ -50,7 +50,7 @@ case $(uname -s) in *) case "$wxGTK_VERSION" in 3) libtoolkit_dev=libgtk-3-dev - extra_deps='libwebkit2gtk-4.0-dev libwebkitgtk-3.0-dev' + extra_deps='libwebkit2gtk-4.0-dev libwebkitgtk-3.0-dev libgtkspell3-3-dev' ;; 2) libtoolkit_dev=libgtk2.0-dev extra_deps='libwebkitgtk-dev' diff --git a/configure b/configure index ef15f342aa..aa6780aed7 100755 --- a/configure +++ b/configure @@ -951,6 +951,8 @@ GTKPRINT_CFLAGS SDL_CONFIG SDL_LIBS SDL_CFLAGS +GTKSPELL_LIBS +GTKSPELL_CFLAGS LIBSECRET_LIBS LIBSECRET_CFLAGS GXX_VERSION @@ -1203,6 +1205,7 @@ enable_printfposparam enable_secretstore enable_snglinst enable_sound +enable_spellcheck enable_stdpaths enable_stopwatch enable_streams @@ -1430,6 +1433,8 @@ MesaGL_CFLAGS MesaGL_LIBS LIBSECRET_CFLAGS LIBSECRET_LIBS +GTKSPELL_CFLAGS +GTKSPELL_LIBS SDL_CFLAGS SDL_LIBS GTKPRINT_CFLAGS @@ -2170,6 +2175,7 @@ Optional Features: --enable-secretstore use wxSecretStore class --enable-snglinst use wxSingleInstanceChecker class --enable-sound use wxSound class + --enable-spellcheck enable spellchecking in wxTextCtrl class (MSW and GTK3 only) --enable-stdpaths use wxStandardPaths class --enable-stopwatch use wxStopWatch class --enable-streams use wxStream etc classes @@ -2467,6 +2473,10 @@ Some influential environment variables: C compiler flags for LIBSECRET, overriding pkg-config LIBSECRET_LIBS linker flags for LIBSECRET, overriding pkg-config + GTKSPELL_CFLAGS + C compiler flags for GTKSPELL, overriding pkg-config + GTKSPELL_LIBS + linker flags for GTKSPELL, overriding pkg-config SDL_CFLAGS C compiler flags for SDL, overriding pkg-config SDL_LIBS linker flags for SDL, overriding pkg-config GTKPRINT_CFLAGS @@ -7863,6 +7873,35 @@ fi eval "$wx_cv_use_sound" + enablestring= + defaultval=$wxUSE_ALL_FEATURES + if test -z "$defaultval"; then + if test x"$enablestring" = xdisable; then + defaultval=yes + else + defaultval=no + fi + fi + + # Check whether --enable-spellcheck was given. +if test "${enable_spellcheck+set}" = set; then : + enableval=$enable_spellcheck; + if test "$enableval" = yes; then + wx_cv_use_spellcheck='wxUSE_SPELLCHECK=yes' + else + wx_cv_use_spellcheck='wxUSE_SPELLCHECK=no' + fi + +else + + wx_cv_use_spellcheck='wxUSE_SPELLCHECK=${'DEFAULT_wxUSE_SPELLCHECK":-$defaultval}" + +fi + + + eval "$wx_cv_use_spellcheck" + + enablestring= defaultval=$wxUSE_ALL_FEATURES if test -z "$defaultval"; then @@ -33935,6 +33974,116 @@ fi fi + +if test "$wxUSE_SPELLCHECK" = "yes"; then + + if test "$wxUSE_MSW" = 1 -o test "$wxUSE_OSX_COCOA" = 1; then + has_spellcheck_support=yes + + elif test "$wxUSE_GTK" = 1; then + if test "$WXGTK3" = 1; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKSPELL" >&5 +$as_echo_n "checking for GTKSPELL... " >&6; } + +if test -n "$PKG_CONFIG"; then + if test -n "$GTKSPELL_CFLAGS"; then + pkg_cv_GTKSPELL_CFLAGS="$GTKSPELL_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtkspell3-3.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtkspell3-3.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKSPELL_CFLAGS=`$PKG_CONFIG --cflags "gtkspell3-3.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GTKSPELL_LIBS"; then + pkg_cv_GTKSPELL_LIBS="$GTKSPELL_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gtkspell3-3.0\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gtkspell3-3.0") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GTKSPELL_LIBS=`$PKG_CONFIG --libs "gtkspell3-3.0" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GTKSPELL_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gtkspell3-3.0"` + else + GTKSPELL_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gtkspell3-3.0"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GTKSPELL_PKG_ERRORS" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: gtkspell3-3.0 not found, spellchecking won't be available" >&5 +$as_echo "$as_me: WARNING: gtkspell3-3.0 not found, spellchecking won't be available" >&2;} + has_spellcheck_support=no + + +elif test $pkg_failed = untried; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: gtkspell3-3.0 not found, spellchecking won't be available" >&5 +$as_echo "$as_me: WARNING: gtkspell3-3.0 not found, spellchecking won't be available" >&2;} + has_spellcheck_support=no + + +else + GTKSPELL_CFLAGS=$pkg_cv_GTKSPELL_CFLAGS + GTKSPELL_LIBS=$pkg_cv_GTKSPELL_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + CXXFLAGS="$GTKSPELL_CFLAGS $CXXFLAGS" + LIBS="$GTKSPELL_LIBS $LIBS" + has_spellcheck_support=yes + +fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Spellchecking is not supported on GTK < 3" >&5 +$as_echo "$as_me: WARNING: Spellchecking is not supported on GTK < 3" >&2;} + has_spellcheck_support=no + fi + + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Spellchecking is not supported on this platform" >&5 +$as_echo "$as_me: WARNING: Spellchecking is not supported on this platform" >&2;} + has_spellcheck_support=no + fi + + if test "$has_spellcheck_support" = "yes"; then + $as_echo "#define wxUSE_SPELLCHECK 1" >>confdefs.h + + fi +fi + + if test "$wxUSE_STL" = "yes"; then $as_echo "#define wxUSE_STL 1" >>confdefs.h diff --git a/configure.in b/configure.in index 7024c62e6d..812d27b0c1 100644 --- a/configure.in +++ b/configure.in @@ -766,6 +766,7 @@ WX_ARG_FEATURE(printfposparam,[ --enable-printfposparam use wxVsnprintf() which WX_ARG_FEATURE(secretstore, [ --enable-secretstore use wxSecretStore class], wxUSE_SECRETSTORE) WX_ARG_FEATURE(snglinst, [ --enable-snglinst use wxSingleInstanceChecker class], wxUSE_SNGLINST_CHECKER) WX_ARG_FEATURE(sound, [ --enable-sound use wxSound class], wxUSE_SOUND) +WX_ARG_FEATURE(spellcheck, [ --enable-spellcheck enable spellchecking in wxTextCtrl class (MSW and GTK3 only)], wxUSE_SPELLCHECK) WX_ARG_FEATURE(stdpaths, [ --enable-stdpaths use wxStandardPaths class], wxUSE_STDPATHS) WX_ARG_FEATURE(stopwatch, [ --enable-stopwatch use wxStopWatch class], wxUSE_STOPWATCH) WX_ARG_FEATURE(streams, [ --enable-streams use wxStream etc classes], wxUSE_STREAMS) @@ -5761,6 +5762,48 @@ if test "$wxUSE_SECRETSTORE" = "yes"; then fi fi + +dnl --------------------------------------------------------------------------- +dnl Spellchecking for wxTextCtrl +dnl --------------------------------------------------------------------------- + +if test "$wxUSE_SPELLCHECK" = "yes"; then + dnl The required APIs are always available under MSW and OS X but we must + dnl have GTK3 and GNOME gtkspell under Unix to be able to compile this feature. + + if test "$wxUSE_MSW" = 1 -o test "$wxUSE_OSX_COCOA" = 1; then + dnl Always available under these systems + has_spellcheck_support=yes + + elif test "$wxUSE_GTK" = 1; then + if test "$WXGTK3" = 1; then + PKG_CHECK_MODULES(GTKSPELL, [gtkspell3-3.0], + [ + CXXFLAGS="$GTKSPELL_CFLAGS $CXXFLAGS" + LIBS="$GTKSPELL_LIBS $LIBS" + has_spellcheck_support=yes + ], + [ + AC_MSG_WARN([gtkspell3-3.0 not found, spellchecking won't be available]) + has_spellcheck_support=no + ] + ) + else + AC_MSG_WARN([Spellchecking is not supported on GTK < 3]) + has_spellcheck_support=no + fi + + else + dnl Not implemented in the other ports yet. + AC_MSG_WARN([Spellchecking is not supported on this platform]) + has_spellcheck_support=no + fi + + if test "$has_spellcheck_support" = "yes"; then + AC_DEFINE(wxUSE_SPELLCHECK) + fi +fi + dnl --------------------------------------------------------------------------- dnl Register non-GUI class options for makefiles and setup.h dnl --------------------------------------------------------------------------- diff --git a/include/wx/android/setup.h b/include/wx/android/setup.h index 7d2516b3aa..e427c6e0b0 100644 --- a/include/wx/android/setup.h +++ b/include/wx/android/setup.h @@ -447,6 +447,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/include/wx/gtk/setup.h b/include/wx/gtk/setup.h index da9678a222..344eec7bab 100644 --- a/include/wx/gtk/setup.h +++ b/include/wx/gtk/setup.h @@ -448,6 +448,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/include/wx/gtk/textctrl.h b/include/wx/gtk/textctrl.h index ebc2f02e0a..296bf73480 100644 --- a/include/wx/gtk/textctrl.h +++ b/include/wx/gtk/textctrl.h @@ -96,6 +96,14 @@ public: // Overridden wxWindow methods virtual void SetWindowStyleFlag( long style ) wxOVERRIDE; +#if wxUSE_SPELLCHECK + // Use native spelling and grammar checking functions. + virtual bool EnableProofCheck(bool WXUNUSED(enable) = true, + const wxTextProofOptions& WXUNUSED(options) = + wxTextProofOptions()) wxOVERRIDE; + virtual bool IsProofCheckEnabled() const wxOVERRIDE; +#endif // wxUSE_SPELLCHECK + // Implementation from now on void OnDropFiles( wxDropFilesEvent &event ); void OnChar( wxKeyEvent &event ); diff --git a/include/wx/motif/setup.h b/include/wx/motif/setup.h index 9e1174e2ab..1783056cbd 100644 --- a/include/wx/motif/setup.h +++ b/include/wx/motif/setup.h @@ -448,6 +448,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/include/wx/msw/setup.h b/include/wx/msw/setup.h index f87bcece45..c45bcebd1e 100644 --- a/include/wx/msw/setup.h +++ b/include/wx/msw/setup.h @@ -448,6 +448,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/include/wx/msw/textctrl.h b/include/wx/msw/textctrl.h index 4b85f69e3c..d7f8d04cc8 100644 --- a/include/wx/msw/textctrl.h +++ b/include/wx/msw/textctrl.h @@ -111,6 +111,15 @@ public: bool ShowNativeCaret(bool show = true); bool HideNativeCaret() { return ShowNativeCaret(false); } +#if wxUSE_RICHEDIT && wxUSE_SPELLCHECK + // Use native spelling and grammar checking functions. + // This is only available in wxTE_RICH2 controls. + virtual bool EnableProofCheck(bool WXUNUSED(enable) = true, + const wxTextProofOptions& WXUNUSED(options) = + wxTextProofOptions()) wxOVERRIDE; + virtual bool IsProofCheckEnabled() const wxOVERRIDE; +#endif // wxUSE_RICHEDIT && wxUSE_SPELLCHECK + // Implementation from now on // -------------------------- diff --git a/include/wx/osx/setup.h b/include/wx/osx/setup.h index e11ce81431..1f62e4b3c2 100644 --- a/include/wx/osx/setup.h +++ b/include/wx/osx/setup.h @@ -454,6 +454,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/include/wx/setup_inc.h b/include/wx/setup_inc.h index 9a59af9816..28dc701f58 100644 --- a/include/wx/setup_inc.h +++ b/include/wx/setup_inc.h @@ -444,6 +444,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/include/wx/textctrl.h b/include/wx/textctrl.h index ac18c183e9..66e3f8135e 100644 --- a/include/wx/textctrl.h +++ b/include/wx/textctrl.h @@ -126,6 +126,45 @@ enum wxTextCtrlHitTestResult }; // ... the character returned +#if wxUSE_SPELLCHECK + +// ---------------------------------------------------------------------------- +// wxTextCtrl proof options object +// Passed to ::EnableProofCheck() to configure the proofing options for +// this control +// ---------------------------------------------------------------------------- +class WXDLLIMPEXP_CORE wxTextProofOptions +{ +public: + wxTextProofOptions(const wxString& lang = wxEmptyString) + : m_lang(lang) + { + m_EnableSpellCheck = true; + m_EnableGrammarCheck = false; + } + + wxTextProofOptions& SpellCheck(bool enable = true) + { + m_EnableSpellCheck = enable; + return *this; + } + + wxTextProofOptions& GrammarCheck(bool enable = true) + { + m_EnableGrammarCheck = enable; + return *this; + } + + const wxString& GetLang() const { return m_lang; } + +private: + wxString m_lang; + bool m_EnableSpellCheck; + bool m_EnableGrammarCheck; +}; + +#endif // wxUSE_SPELLCHECK + // ---------------------------------------------------------------------------- // Types for wxTextAttr // ---------------------------------------------------------------------------- @@ -758,6 +797,15 @@ public: virtual const wxTextEntry* WXGetTextEntry() const wxOVERRIDE { return this; } +#if wxUSE_SPELLCHECK + // Use native spelling and grammar checking functions. + virtual bool EnableProofCheck(bool WXUNUSED(enable) = true, + const wxTextProofOptions& WXUNUSED(options) = + wxTextProofOptions()) + { return false; } + virtual bool IsProofCheckEnabled() const { return false; } +#endif // wxUSE_SPELLCHECK + protected: // Override wxEvtHandler method to check for a common problem of binding // wxEVT_TEXT_ENTER to a control without wxTE_PROCESS_ENTER style, which is diff --git a/include/wx/univ/setup.h b/include/wx/univ/setup.h index 010713e897..fcf5db2d92 100644 --- a/include/wx/univ/setup.h +++ b/include/wx/univ/setup.h @@ -447,6 +447,18 @@ // Recommended setting: 1 (but may be safely disabled if you don't use it) #define wxUSE_SECRETSTORE 1 +// Allow the use of the OS built-in spellchecker on wxTextCtrl (multiline +// only). Currently only wxGTK3 and wxMSW are implemented. +// +// Default is 1 on wxGTK3 and wxMSW platforms and 0 otherwise. +// +// Recommended setting: 1 on supported platforms. +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 1 +#else +#define wxUSE_SPELLCHECK 0 +#endif + // Use wxStandardPaths class which allows to retrieve some standard locations // in the file system // diff --git a/interface/wx/textctrl.h b/interface/wx/textctrl.h index d296d05c72..f888778f41 100644 --- a/interface/wx/textctrl.h +++ b/interface/wx/textctrl.h @@ -258,7 +258,6 @@ enum wxTextCtrlHitTestResult wxTE_HT_BEYOND }; - /** @class wxTextAttr @@ -979,6 +978,62 @@ public: void operator=(const wxTextAttr& attr); }; +/** + @class wxTextProofOptions + + This class provides a convenient means of passing multiple parameters to + wxTextCtrl::EnableProofCheck(). Typical (and the default) usage is: + + @code + m_pText->EnableProofCheck(true, wxTextProofOptions(wxEmptyString).SpellCheck(true)); + @endcode + + If this is the exact behaviour desired, then the parameters can be omitted. + The following code will have the same result: + + @code + m_pText->EnableProofCheck(); + @endcode + + Options can also be cascaded if required as follows: + + @code + m_pText->EnableProofCheck(true, wxTextProofOptions("fr_FR").SpellCheck(false).GrammarCheck(true)); + @endcode + + @see wxTextCtrl::EnableProofCheck(), wxTextCtrl::IsProofCheckEnabled(). +*/ +class WXDLLIMPEXP_CORE wxTextProofOptions +{ + /** + Default constructor. The proofing language is set to the current locale language, + spell checking is enabled and grammar checking is disabled. + + @param lang + The ISO 639 / ISO 3166 canonical language name of the dictionary + to be used. See wxLocale::GetCanonicalName() for examples. If an + empty string is passed (default), then the current locale will be + used. This parameter is ignored and only the current locale + language (default option) is supported at this time. + */ + wxTextProofOptions(const wxString& lang = wxEmptyString) + + /** + Enable / disable spell checking for this control. + + This option is currently hard coded to @true and is ignored. + Use the global enable parameter passed to + wxTextCtrl::EnableProofCheck() to enable / disable spell checking. + */ + wxTextProofOptions& SpellCheck(bool enable = true) + + /** + Enable / disable grammar checking for this control. + + This option is not currently supported and is ignored. + */ + wxTextProofOptions& GrammarCheck(bool enable = true) +}; /** @class wxTextCtrl @@ -1336,6 +1391,34 @@ public: */ virtual bool EmulateKeyPress(const wxKeyEvent& event); + /** + Enable or disable native spell checking on this text control if it is + available on the current platform. + + @onlyfor{wxmsw,wxgtk} + Currently wxMSW (>= Windows 7) and wxGTK3 are supported. In addition, + wxMSW use requires that the text control has the wxTE_RICH2 style + set. wxGTK3 requires that the control has the wxTE_MULTILINE style. + + @param enable + Enables native proof checking if true, disables it otherwise. + + @param options + A wxTextProofOptions object specifying the desired behaviour + of the proof checker (e.g. language to use, spell check, grammar + check, etc.). This parameter is currently unused and the control is + initialised with the default setting of current locale language / + spell check only. + + @return + @true if proof checking has been successfully enabled (and true was + passed as the enable parameter), @false otherwise. + + @since 3.1.6 + */ + virtual bool EnableProofCheck(bool enable = true, + const wxTextProofOptions& options = wxTextProofOptions()); + /** Returns the style currently used for the new text. @@ -1477,6 +1560,18 @@ public: */ bool IsSingleLine() const; + /** + Returns @true if proof (spell) checking is currently active on this + control, @false otherwise. + + @onlyfor{wxmsw,wxgtk} + + @see EnableProofCheck() + + @since 3.1.6 + */ + virtual bool IsProofCheckEnabled(); + /** Loads and displays the named file, if it exists. diff --git a/samples/text/text.cpp b/samples/text/text.cpp index 892cd0ad36..120877f2ae 100644 --- a/samples/text/text.cpp +++ b/samples/text/text.cpp @@ -1205,9 +1205,22 @@ MyPanel::MyPanel( wxFrame *frame, int x, int y, int w, int h ) m_tab->SetClientData(const_cast(static_cast(wxS("tab")))); m_enter = new MyTextCtrl( this, 100, "Multiline, allow processing.", - wxPoint(180,170), wxSize(200,70), wxTE_MULTILINE | wxTE_PROCESS_ENTER ); + wxPoint(180,170), wxSize(200,70), wxTE_MULTILINE | wxTE_PROCESS_ENTER | wxTE_RICH2 ); m_enter->SetClientData(const_cast(static_cast(wxS("enter")))); +#if wxUSE_SPELLCHECK + if ( !m_enter->EnableProofCheck(true, wxTextProofOptions("en_US").SpellCheck()) ) + { + wxMessageDialog error(this, + wxT("Spell checking is not available on this platform or control style."), + wxT("Spell checker error"), + wxOK | wxCENTER | wxICON_ERROR); + error.ShowModal(); + } + else + (*m_enter) << wxT("\nSpell checking is enabled, try typing a misspelled word..."); +#endif + m_textrich = new MyTextCtrl(this, wxID_ANY, "Allows more than 30Kb of text\n" "(on all Windows versions)\n" "and a very very very very very " diff --git a/setup.h.in b/setup.h.in index 673e540222..159f6c8989 100644 --- a/setup.h.in +++ b/setup.h.in @@ -216,6 +216,12 @@ #define wxUSE_SECRETSTORE 0 +#if (defined(__WXGTK3__) || defined(__WXMSW__)) +#define wxUSE_SPELLCHECK 0 +#else +#define wxUSE_SPELLCHECK 0 +#endif + #define wxUSE_STDPATHS 0 #define wxUSE_TEXTBUFFER 0 diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 86adcd3bd4..4d43c3e824 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -32,6 +32,12 @@ #include "wx/gtk/private.h" #include "wx/gtk/private/gtk3-compat.h" +#if wxUSE_SPELLCHECK +extern "C" { +#include +} +#endif // wxUSE_SPELLCHECK + // ---------------------------------------------------------------------------- // helpers // ---------------------------------------------------------------------------- @@ -1017,6 +1023,57 @@ void wxTextCtrl::GTKSetJustification() } } +#if wxUSE_SPELLCHECK + +bool wxTextCtrl::EnableProofCheck(bool enable, const wxTextProofOptions& options) +{ + wxCHECK_MSG( IsMultiLine(), false, + "Unable to enable spell check on control " + "which does not have wxTE_MULTILINE style" ); + + GtkTextView *textview = GTK_TEXT_VIEW(m_text); + wxCHECK_MSG( textview, false, wxS("wxTextCtrl is not a GtkTextView")); + + GtkSpellChecker *spell = gtk_spell_checker_get_from_text_view(textview); + + if ( enable ) + { + if ( !spell ) + { + spell = gtk_spell_checker_new(); + gtk_spell_checker_attach(spell, textview); + } + + wxString lang = options.GetLang(); + + if ( !gtk_spell_checker_set_language(spell, + lang.empty() ? NULL : (const gchar *)lang.utf8_str(), + NULL) ) + return false; + } + else + { + if ( spell ) + gtk_spell_checker_detach(spell); + } + + return IsProofCheckEnabled(); +} + +bool wxTextCtrl::IsProofCheckEnabled() const +{ + GtkTextView *textview = GTK_TEXT_VIEW(m_text); + + if ( !IsMultiLine() || textview == NULL ) + return false; + + GtkSpellChecker *spell = gtk_spell_checker_get_from_text_view(textview); + + return (spell != NULL); +} + +#endif // wxUSE_SPELLCHECK + void wxTextCtrl::SetWindowStyleFlag(long style) { long styleOld = GetWindowStyleFlag(); diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 2819131b4d..47f4bc553c 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -19,7 +19,6 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" - #if wxUSE_TEXTCTRL #ifndef WX_PRECOMP @@ -77,6 +76,27 @@ #include "wx/msw/ole/oleutils.h" #include "wx/msw/private/comptr.h" + + #if wxUSE_SPELLCHECK + #include "wx/msw/wrapwin.h" + + // Add defines that are missing in MinGW. + #ifndef IMF_SPELLCHECKING + #define IMF_SPELLCHECKING 0x0800 + #endif + #ifndef SES_USECTF + #define SES_USECTF 0x00010000 + #endif + #ifndef SES_CTFALLOWEMBED + #define SES_CTFALLOWEMBED 0x00200000 + #endif + #ifndef SES_CTFALLOWSMARTTAG + #define SES_CTFALLOWSMARTTAG 0x00400000 + #endif + #ifndef SES_CTFALLOWPROOFING + #define SES_CTFALLOWPROOFING 0x00800000 + #endif + #endif // wxUSE_SPELLCHECK #endif // wxUSE_RICHEDIT #if wxUSE_INKEDIT @@ -812,6 +832,39 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const return msStyle; } +#if wxUSE_RICHEDIT && wxUSE_SPELLCHECK + +bool wxTextCtrl::EnableProofCheck(bool enable, const wxTextProofOptions& WXUNUSED(options)) +{ + wxCHECK_MSG((m_windowStyle & wxTE_RICH2), false, + "Unable to enable proof checking on a control " + "that does not have wxTE_RICH2 style"); + + LPARAM editStyle = SES_USECTF | SES_CTFALLOWEMBED + | SES_CTFALLOWSMARTTAG | SES_CTFALLOWPROOFING; + ::SendMessage(GetHwnd(), EM_SETEDITSTYLE, editStyle, editStyle); + + LRESULT langOptions = ::SendMessage(GetHwnd(), EM_GETLANGOPTIONS, 0, 0); + + if ( enable ) + langOptions |= IMF_SPELLCHECKING; + else + langOptions &= ~IMF_SPELLCHECKING; + + ::SendMessage(GetHwnd(), EM_SETLANGOPTIONS, 0, langOptions); + + return IsProofCheckEnabled(); +} + +bool wxTextCtrl::IsProofCheckEnabled() const +{ + LRESULT langOptions = ::SendMessage(GetHwnd(), EM_GETLANGOPTIONS, 0, 0); + + return (langOptions & IMF_SPELLCHECKING); +} + +#endif // wxUSE_SPELLCHECK + void wxTextCtrl::SetWindowStyleFlag(long style) { // changing the alignment of the control dynamically works under Win2003