X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/b7a3ba7dcd3b2477a6383229159472b803742d7c..ff0d9d83cd088b9f7c925db8262f86674a320724:/src/msw/textctrl.cpp diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index 0dd0da0b7b..8e7fd4e662 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/textctrl.cpp +// Name: src/msw/textctrl.cpp // Purpose: wxTextCtrl // Author: Julian Smart // Modified by: @@ -36,9 +36,10 @@ #include "wx/app.h" #include "wx/menu.h" #include "wx/math.h" + #include "wx/module.h" #endif -#include "wx/module.h" +#include "wx/sysopt.h" #if wxUSE_CLIPBOARD #include "wx/clipbrd.h" @@ -50,6 +51,7 @@ #include "wx/msw/private.h" #include "wx/msw/winundef.h" +#include "wx/msw/mslu.h" #include #include @@ -60,16 +62,20 @@ #if wxUSE_RICHEDIT +#if wxUSE_INKEDIT +#include "wx/dynlib.h" +#endif + // old mingw32 has richedit stuff directly in windows.h and doesn't have // richedit.h at all #if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__) #include #endif -#include "wx/msw/missing.h" - #endif // wxUSE_RICHEDIT +#include "wx/msw/missing.h" + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -94,15 +100,30 @@ public: // load the richedit DLL for the specified version of rich edit static bool Load(Version version); +#if wxUSE_INKEDIT + // load the InkEdit library + static bool LoadInkEdit(); +#endif + private: // the handles to richedit 1.0 and 2.0 (or 3.0) DLLs static HINSTANCE ms_hRichEdit[Version_Max]; +#if wxUSE_INKEDIT + static wxDynamicLibrary ms_inkEditLib; + static bool ms_inkEditLibLoadAttemped; +#endif + DECLARE_DYNAMIC_CLASS(wxRichEditModule) }; HINSTANCE wxRichEditModule::ms_hRichEdit[Version_Max] = { NULL, NULL, NULL }; +#if wxUSE_INKEDIT +wxDynamicLibrary wxRichEditModule::ms_inkEditLib; +bool wxRichEditModule::ms_inkEditLibLoadAttemped = false; +#endif + IMPLEMENT_DYNAMIC_CLASS(wxRichEditModule, wxModule) #endif // wxUSE_RICHEDIT @@ -115,9 +136,13 @@ public: UpdatesCountFilter(int& count) : m_count(count) { - wxASSERT_MSG( m_count == -1, _T("wrong initial m_updatesCount value") ); + wxASSERT_MSG( m_count == -1 || m_count == -2, + _T("wrong initial m_updatesCount value") ); - m_count = 0; + if (m_count != -2) + m_count = 0; + //else: we don't want to count how many update events we get as we're going + // to ignore all of them } ~UpdatesCountFilter() @@ -186,7 +211,7 @@ wxBEGIN_FLAGS( wxTextCtrlStyle ) wxFLAGS_MEMBER(wxTE_CENTRE) wxFLAGS_MEMBER(wxTE_RIGHT) wxFLAGS_MEMBER(wxTE_DONTWRAP) - wxFLAGS_MEMBER(wxTE_LINEWRAP) + wxFLAGS_MEMBER(wxTE_CHARWRAP) wxFLAGS_MEMBER(wxTE_WORDWRAP) wxEND_FLAGS( wxTextCtrlStyle ) @@ -207,11 +232,11 @@ wxEND_HANDLERS_TABLE() wxCONSTRUCTOR_6( wxTextCtrl , wxWindow* , Parent , wxWindowID , Id , wxString , Value , wxPoint , Position , wxSize , Size , long , WindowStyle) #else -IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxControl) +IMPLEMENT_DYNAMIC_CLASS(wxTextCtrl, wxTextCtrlBase) #endif -BEGIN_EVENT_TABLE(wxTextCtrl, wxControl) +BEGIN_EVENT_TABLE(wxTextCtrl, wxTextCtrlBase) EVT_CHAR(wxTextCtrl::OnChar) EVT_DROP_FILES(wxTextCtrl::OnDropFiles) @@ -252,6 +277,10 @@ void wxTextCtrl::Init() m_verRichEdit = 0; #endif // wxUSE_RICHEDIT +#if wxUSE_INKEDIT && wxUSE_RICHEDIT + m_isInkEdit = 0; +#endif + m_privateContextMenu = NULL; m_updatesCount = -1; m_isNativeCaretShown = true; @@ -262,7 +291,8 @@ wxTextCtrl::~wxTextCtrl() delete m_privateContextMenu; } -bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, +bool wxTextCtrl::Create(wxWindow *parent, + wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, @@ -279,6 +309,16 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, if ( !CreateControl(parent, id, pos, size, style, validator, name) ) return false; + if ( !MSWCreateText(value, pos, size) ) + return false; + + return true; +} + +bool wxTextCtrl::MSWCreateText(const wxString& value, + const wxPoint& pos, + const wxSize& size) +{ // translate wxWin style flags to MSW ones WXDWORD msStyle = MSWGetCreateWindowFlags(); @@ -287,7 +327,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, #if defined(__POCKETPC__) || defined(__SMARTPHONE__) // A control that capitalizes the first letter - if (style & wxTE_CAPITALIZE) + if ( HasFlag(wxTE_CAPITALIZE) ) windowClass = wxT("CAPEDIT"); #endif @@ -321,49 +361,76 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, m_verRichEdit = m_windowStyle & wxTE_RICH2 ? 2 : 1; #endif // wxUSE_UNICODE/!wxUSE_UNICODE - if ( m_verRichEdit == 2 ) +#if wxUSE_INKEDIT + // First test if we can load an ink edit control. Normally, all edit + // controls will be made ink edit controls if a tablet environment is + // found (or if msw.inkedit != 0 and the InkEd.dll is present). + // However, an application can veto ink edit controls by either specifying + // msw.inkedit = 0 or by removing wxTE_RICH[2] from the style. + // + if ((wxSystemSettings::HasFeature(wxSYS_TABLET_PRESENT) || wxSystemOptions::GetOptionInt(wxT("msw.inkedit")) != 0) && + !(wxSystemOptions::HasOption(wxT("msw.inkedit")) && wxSystemOptions::GetOptionInt(wxT("msw.inkedit")) == 0)) { - if ( wxRichEditModule::Load(wxRichEditModule::Version_41) ) + if (wxRichEditModule::LoadInkEdit()) { - // yes, class name for version 4.1 really is 5.0 - windowClass = _T("RICHEDIT50W"); + windowClass = INKEDIT_CLASS; + +#if wxUSE_INKEDIT && wxUSE_RICHEDIT + m_isInkEdit = 1; +#endif + + // Fake rich text version for other calls + m_verRichEdit = 2; } - else if ( wxRichEditModule::Load(wxRichEditModule::Version_2or3) ) + } +#endif + + if (!IsInkEdit()) + { + if ( m_verRichEdit == 2 ) { - windowClass = _T("RichEdit20") + if ( wxRichEditModule::Load(wxRichEditModule::Version_41) ) + { + // yes, class name for version 4.1 really is 5.0 + windowClass = _T("RICHEDIT50W"); + } + else if ( wxRichEditModule::Load(wxRichEditModule::Version_2or3) ) + { + windowClass = _T("RichEdit20") #if wxUSE_UNICODE - _T("W"); + _T("W"); #else // ANSI - _T("A"); + _T("A"); #endif // Unicode/ANSI + } + else // failed to load msftedit.dll and riched20.dll + { + m_verRichEdit = 1; + } } - else // failed to load msftedit.dll and riched20.dll - { - m_verRichEdit = 1; - } - } - if ( m_verRichEdit == 1 ) - { - if ( wxRichEditModule::Load(wxRichEditModule::Version_1) ) - { - windowClass = _T("RICHEDIT"); - } - else // failed to load any richedit control DLL + if ( m_verRichEdit == 1 ) { - // only give the error msg once if the DLL can't be loaded - static bool s_errorGiven = false; // MT ok as only used by GUI - - if ( !s_errorGiven ) + if ( wxRichEditModule::Load(wxRichEditModule::Version_1) ) { - wxLogError(_("Impossible to create a rich edit control, using simple text control instead. Please reinstall riched32.dll")); - - s_errorGiven = true; + windowClass = _T("RICHEDIT"); } + else // failed to load any richedit control DLL + { + // only give the error msg once if the DLL can't be loaded + static bool s_errorGiven = false; // MT ok as only used by GUI + + if ( !s_errorGiven ) + { + wxLogError(_("Impossible to create a rich edit control, using simple text control instead. Please reinstall riched32.dll")); - m_verRichEdit = 0; + s_errorGiven = true; + } + + m_verRichEdit = 0; + } } - } + } // !useInkEdit } #endif // wxUSE_RICHEDIT @@ -382,13 +449,25 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, return false; #if wxUSE_RICHEDIT - if ( IsRich() ) + if (IsRich()) { +#if wxUSE_INKEDIT + if (IsInkEdit()) + { + // Pass IEM_InsertText (0) as wParam, in order to have the ink always + // converted to text. + ::SendMessage(GetHwnd(), EM_SETINKINSERTMODE, 0, 0); + + // Make sure the mouse can be used for input + ::SendMessage(GetHwnd(), EM_SETUSEMOUSEFORINPUT, 1, 0); + } +#endif + // enable the events we're interested in: we want to get EN_CHANGE as // for the normal controls LPARAM mask = ENM_CHANGE; - if ( GetRichVersion() == 1 ) + if (GetRichVersion() == 1 && !IsInkEdit()) { // we also need EN_MSGFILTER for richedit 1.0 for the reasons // explained in its handler @@ -403,7 +482,7 @@ bool wxTextCtrl::Create(wxWindow *parent, wxWindowID id, // Windows XP, so if we're sure it works correctly under other // systems we could do this only for XP SetSize(-1, 1); // 1 is small enough to force vert scrollbar - SetSize(size); + SetInitialSize(size); } else if ( m_windowStyle & wxTE_AUTO_URL ) { @@ -468,9 +547,6 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const // styles which we alaways add by default if ( style & wxTE_MULTILINE ) { - wxASSERT_MSG( !(style & wxTE_PROCESS_ENTER), - wxT("wxTE_PROCESS_ENTER style is ignored for multiline text controls (they always process it)") ); - msStyle |= ES_MULTILINE | ES_WANTRETURN; if ( !(style & wxTE_NO_VSCROLL) ) { @@ -532,6 +608,62 @@ WXDWORD wxTextCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const void wxTextCtrl::SetWindowStyleFlag(long style) { + // changing the alignment of the control dynamically works under Win2003 + // (but not older Windows version: it seems to work under some versions of + // XP but not other ones, and we have no way to determine it so be + // conservative here) and only for plain EDIT controls (not RICH ones) and + // we have to recreate the control to make it always work + if ( IsRich() || wxGetWinVersion() < wxWinVersion_2003 ) + { + const long alignMask = wxTE_LEFT | wxTE_CENTRE | wxTE_RIGHT; + if ( (style & alignMask) != (GetWindowStyle() & alignMask) ) + { + const wxString value = GetValue(); + const wxPoint pos = GetPosition(); + const wxSize size = GetSize(); + + // delete the old window + HWND hwnd = GetHwnd(); + DissociateHandle(); + ::DestroyWindow(hwnd); + + // create the new one with the updated flags + m_windowStyle = style; + MSWCreateText(value, pos, size); + + // and make sure it has the same attributes as before + if ( m_hasFont ) + { + // calling SetFont(m_font) would do nothing as the code would + // notice that the font didn't change, so force it to believe + // that it did + wxFont font = m_font; + m_font = wxNullFont; + SetFont(font); + } + + if ( m_hasFgCol ) + { + wxColour colFg = m_foregroundColour; + m_foregroundColour = wxNullColour; + SetForegroundColour(colFg); + } + + if ( m_hasBgCol ) + { + wxColour colBg = m_backgroundColour; + m_backgroundColour = wxNullColour; + SetBackgroundColour(colBg); + } + + // note that text styles are lost but this is probably not a big + // problem: if you use styles, you probably don't use nor change + // alignment flags anyhow + + return; + } + } + #if wxUSE_RICHEDIT // we have to deal with some styles separately because they can't be // changed by simply calling SetWindowLong(GWL_STYLE) but can be changed @@ -553,6 +685,15 @@ void wxTextCtrl::SetWindowStyleFlag(long style) // set/get the controls text // ---------------------------------------------------------------------------- +bool wxTextCtrl::IsEmpty() const +{ + // this is an optimization for multiline controls containing a lot of text + if ( IsMultiLine() && GetNumberOfLines() != 1 ) + return false; + + return wxTextCtrlBase::IsEmpty(); +} + wxString wxTextCtrl::GetValue() const { // range 0..-1 is special for GetRange() and means to retrieve all text @@ -676,7 +817,7 @@ wxString wxTextCtrl::GetRange(long from, long to) const return str; } -void wxTextCtrl::SetValue(const wxString& value) +void wxTextCtrl::DoSetValue(const wxString& value, int flags) { // if the text is long enough, it's faster to just set it instead of first // comparing it with the old one (chances are that it will be different @@ -684,22 +825,27 @@ void wxTextCtrl::SetValue(const wxString& value) // edit controls mostly) if ( (value.length() > 0x400) || (value != GetValue()) ) { - DoWriteText(value, false /* not selection only */); + DoWriteText(value, flags /* doesn't include SelectionOnly here */); + + // mark the control as being not dirty - we changed its text, not the + // user + DiscardEdits(); // for compatibility, don't move the cursor when doing SetValue() SetInsertionPoint(0); } else // same text { + // still reset the modified flag even if the value didn't really change + // because now it comes from the program and not the user (and do it + // before generating the event so that the event handler could get the + // expected value from IsModified()) + DiscardEdits(); + // still send an event for consistency - SendUpdateEvent(); + if (flags & SetValue_SendEvent) + SendUpdateEvent(); } - - // we should reset the modified flag even if the value didn't really change - - // mark the control as being not dirty - we changed its text, not the - // user - DiscardEdits(); } #if wxUSE_RICHEDIT && (!wxUSE_UNICODE || wxUSE_UNICODE_MSLU) @@ -896,8 +1042,9 @@ void wxTextCtrl::WriteText(const wxString& value) DoWriteText(value); } -void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly) +void wxTextCtrl::DoWriteText(const wxString& value, int flags) { + bool selectionOnly = (flags & SetValue_SelectionOnly) != 0; wxString valueDos; if ( m_windowStyle & wxTE_MULTILINE ) valueDos = wxTextFile::Translate(value, wxTextFileType_Dos); @@ -961,13 +1108,16 @@ void wxTextCtrl::DoWriteText(const wxString& value, bool selectionOnly) // we generate exactly one of them by ignoring all but the first one in // SendUpdateEvent() and generating one ourselves if we hadn't got any // notifications from Windows + if ( !(flags & SetValue_SendEvent) ) + m_updatesCount = -2; // suppress any update event + UpdatesCountFilter ucf(m_updatesCount); ::SendMessage(GetHwnd(), selectionOnly ? EM_REPLACESEL : WM_SETTEXT, // EM_REPLACESEL takes 1 to indicate the operation should be redoable - selectionOnly ? 1 : 0, (LPARAM)valueDos.c_str()); + selectionOnly ? 1 : 0, (LPARAM)valueDos.wx_str()); - if ( !ucf.GotUpdate() ) + if ( !ucf.GotUpdate() && (flags & SetValue_SendEvent) ) { SendUpdateEvent(); } @@ -1121,7 +1271,8 @@ void wxTextCtrl::SetInsertionPointEnd() // if it doesn't actually move the caret anywhere and so the simple fact of // doing it results in horrible flicker when appending big amounts of text // to the control in a few chunks (see DoAddText() test in the text sample) - if ( GetInsertionPoint() == GetLastPosition() ) + const wxTextPos lastPosition = GetLastPosition(); + if ( GetInsertionPoint() == lastPosition ) { return; } @@ -1137,7 +1288,7 @@ void wxTextCtrl::SetInsertionPointEnd() else // !RichEdit 1.0 #endif // wxUSE_RICHEDIT { - pos = GetLastPosition(); + pos = lastPosition; } SetInsertionPoint(pos); @@ -1295,9 +1446,9 @@ void wxTextCtrl::DoSetSelection(long from, long to, bool scrollCaret) // Working with files // ---------------------------------------------------------------------------- -bool wxTextCtrl::LoadFile(const wxString& file) +bool wxTextCtrl::DoLoadFile(const wxString& file, int fileType) { - if ( wxTextCtrlBase::LoadFile(file) ) + if ( wxTextCtrlBase::DoLoadFile(file, fileType) ) { // update the size limit if needed AdjustSpaceLimit(); @@ -1317,7 +1468,7 @@ void wxTextCtrl::Replace(long from, long to, const wxString& value) // Set selection and remove it DoSetSelection(from, to, false /* don't scroll caret into view */); - DoWriteText(value, true /* selection only */); + DoWriteText(value); } void wxTextCtrl::Remove(long from, long to) @@ -1672,18 +1823,17 @@ void wxTextCtrl::OnDropFiles(wxDropFilesEvent& event) // kbd input processing // ---------------------------------------------------------------------------- -bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg) +bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* msg) { - MSG *msg = (MSG *)pMsg; - // check for our special keys here: if we don't do it and the parent frame // uses them as accelerators, they wouldn't work at all, so we disable // usual preprocessing for them if ( msg->message == WM_KEYDOWN ) { - WORD vkey = (WORD) msg->wParam; - if ( (HIWORD(msg->lParam) & KF_ALTDOWN) == KF_ALTDOWN ) + const WPARAM vkey = msg->wParam; + if ( HIWORD(msg->lParam) & KF_ALTDOWN ) { + // Alt-Backspace is accelerator for "Undo" if ( vkey == VK_BACK ) return false; } @@ -1701,6 +1851,9 @@ bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg) // fall through case 0: + if ( IsMultiLine() && vkey == VK_RETURN ) + return false; + // fall through case 2: break; @@ -1729,7 +1882,7 @@ bool wxTextCtrl::MSWShouldPreProcessMessage(WXMSG* pMsg) } } - return wxControl::MSWShouldPreProcessMessage(pMsg); + return wxControl::MSWShouldPreProcessMessage(msg); } void wxTextCtrl::OnChar(wxKeyEvent& event) @@ -1737,16 +1890,15 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) switch ( event.GetKeyCode() ) { case WXK_RETURN: - if ( !HasFlag(wxTE_MULTILINE) ) { wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); InitCommandEvent(event); event.SetString(GetValue()); if ( GetEventHandler()->ProcessEvent(event) ) + if ( !HasFlag(wxTE_MULTILINE) ) return; + //else: multiline controls need Enter for themselves } - //else: multiline controls need Enter for themselves - break; case WXK_TAB: @@ -1795,41 +1947,53 @@ WXLRESULT wxTextCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lPara { WXLRESULT lRc = wxTextCtrlBase::MSWWindowProc(nMsg, wParam, lParam); - if ( nMsg == WM_GETDLGCODE ) + switch ( nMsg ) { - // we always want the chars and the arrows: the arrows for navigation - // and the chars because we want Ctrl-C to work even in a read only - // control - long lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS; + case WM_GETDLGCODE: + { + // we always want the chars and the arrows: the arrows for + // navigation and the chars because we want Ctrl-C to work even + // in a read only control + long lDlgCode = DLGC_WANTCHARS | DLGC_WANTARROWS; - if ( IsEditable() ) - { - // we may have several different cases: - // 1. normal case: both TAB and ENTER are used for dlg navigation - // 2. ctrl which wants TAB for itself: ENTER is used to pass to the - // next control in the dialog - // 3. ctrl which wants ENTER for itself: TAB is used for dialog - // navigation - // 4. ctrl which wants both TAB and ENTER: Ctrl-ENTER is used to go - // to the next control - - // the multiline edit control should always get for itself - if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) ) - lDlgCode |= DLGC_WANTMESSAGE; - - if ( HasFlag(wxTE_PROCESS_TAB) ) - lDlgCode |= DLGC_WANTTAB; - - lRc |= lDlgCode; - } - else // !editable - { - // NB: use "=", not "|=" as the base class version returns the - // same flags is this state as usual (i.e. including - // DLGC_WANTMESSAGE). This is strange (how does it work in the - // native Win32 apps?) but for now live with it. - lRc = lDlgCode; - } + if ( IsEditable() ) + { + // we may have several different cases: + // 1. normal: both TAB and ENTER are used for navigation + // 2. ctrl wants TAB for itself: ENTER is used to pass to + // the next control in the dialog + // 3. ctrl wants ENTER for itself: TAB is used for dialog + // navigation + // 4. ctrl wants both TAB and ENTER: Ctrl-ENTER is used to + // go to the next control (we need some way to do it) + + // multiline controls should always get ENTER for themselves + if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) ) + lDlgCode |= DLGC_WANTMESSAGE; + + if ( HasFlag(wxTE_PROCESS_TAB) ) + lDlgCode |= DLGC_WANTTAB; + + lRc |= lDlgCode; + } + else // !editable + { + // NB: use "=", not "|=" as the base class version returns + // the same flags is this state as usual (i.e. + // including DLGC_WANTMESSAGE). This is strange (how + // does it work in the native Win32 apps?) but for now + // live with it. + lRc = lDlgCode; + } + } + break; + + case WM_CUT: + case WM_COPY: + case WM_PASTE: + if ( HandleClipboardEvent(nMsg) ) + lRc = 0; + break; } return lRc; @@ -1860,6 +2024,11 @@ bool wxTextCtrl::SendUpdateEvent() // we hadn't updated the control ourselves, this event comes from // the user, don't need to ignore it nor update the count break; + + case -2: + // the control was updated programmatically and we do NOT want to + // send events + return false; } wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId()); @@ -2453,11 +2622,23 @@ bool wxTextCtrl::SetStyle(long start, long end, const wxTextAttr& style) } } - if (pf.dwMask != 0) +#if wxUSE_RICHEDIT2 + if ( m_verRichEdit > 1 ) + { + if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft ) + { + // Use RTL paragraphs in RTL mode to get proper layout + pf.dwMask |= PFM_RTLPARA; + pf.wEffects |= PFE_RTLPARA; + } + } +#endif // wxUSE_RICHEDIT2 + + if ( pf.dwMask ) { // do format the selection bool ok = ::SendMessage(GetHwnd(), EM_SETPARAFORMAT, - 0, (LPARAM) &pf) != 0; + 0, (LPARAM) &pf) != 0; if ( !ok ) { wxLogDebug(_T("SendMessage(EM_SETPARAFORMAT, 0) failed")); @@ -2660,6 +2841,10 @@ void wxRichEditModule::OnExit() ms_hRichEdit[i] = NULL; } } +#if wxUSE_INKEDIT + if (ms_inkEditLib.IsLoaded()) + ms_inkEditLib.Unload(); +#endif } /* static */ @@ -2699,6 +2884,23 @@ bool wxRichEditModule::Load(Version version) return true; } +#if wxUSE_INKEDIT +// load the InkEdit library +bool wxRichEditModule::LoadInkEdit() +{ + static wxDynamicLibrary ms_inkEditLib; + static bool ms_inkEditLibLoadAttemped; + if (ms_inkEditLibLoadAttemped) + ms_inkEditLib.IsLoaded(); + + ms_inkEditLibLoadAttemped = true; + + wxLogNull logNull; + return ms_inkEditLib.Load(wxT("inked")); +} +#endif + + #endif // wxUSE_RICHEDIT #endif // wxUSE_TEXTCTRL && !(__SMARTPHONE__ && __WXWINCE__)